I’m using swing to display multiple javafx Tableview, each embeded (thanks to JFXPanel) in a swing TabbedPane
I use the well know pattern described in the oracle doc, in scala way :
implicit def fun2Run[T](x: ⇒ T) = new Runnable {
def run = x
}
def myTabbedScene():Scene = {
val root = new StackPane
root.getChildren.add(new Label("Hello world!"))
new Scene(root, 300, 300)
}
def initFxPanel(fxPanel: JFXPanel, s: ⇒ Scene) = {
fxPanel.setScene(s)
}
def initSwingGui(panel: PluginPanel) = {
val fxPanel = new JFXPanel()
// code to add panel to JPanel
panel.peer.add(fxPanel)
Platform runLater initFxPanel(fxPanel,myTabbedScene())
}
val jfxSwingPanel = new PluginPanel("wrap 2") {
var jtemp = new JPanel()
contents += jtemp
}
SwingUtilities invokeLater initSwingGui(jfxSwingPanel)
This code is executed each time the user open a new swing tab (only scene method differs) but i’m not sure this is the best way to manage thread in this case :-/
When i close or open a tab, i have some incoherent state in my application and error during display.
An example of my use case, and somes questions linked :
-
I open a first tab J1, a runlater is invoked, my scene display without problem in the tab.
-
I open a second tab J2, a new runlater is invoked on javafx Thread,
-
I switch to tab J1, how display in my tab is refresh ? An implicit
runnableaction is launched to main thread to make this possible ? How javafx recognized the good tab to refresh ? If i have a button which launch some action, i launch arunlater()action on the javafx main thread which dispatch ?
Update:
I find a code source which can help reader on this point, you can revalidate() or/and repaint() your swing panel (here _contentpane) which contain your jfxPanel
SwingUtilities.invokeLater(new Runnable() {
public void run() {
_contentPane.add(_jfxPanel);
_contentPane.revalidate();
_contentPane.repaint(); }});
- I close the first tab J1, javafx automaticly close/garbage the javafx resource associated?
I have multiples other general questions :
-
How javafx application main thread manage this multiple runlater() call
when they arrive from different jfxpanel in swing ? -
How can i close properly the resources (without close main javafx thread with exit() Platform method) associated to my jfxpanel when user close a tab ? If i destroy the JFXPanel,javafx resources used to display are liberated ?
-
Using task to manage my thread can be an answer to my problem ?
My question are probably naive, but i start in gui building, and i have problem to understand how javafx manage scene on different embedded panel.
From the Platform.runLater javadoc:
Further:
It’s unclear which thread you are referring to. In general, when integrating JavaFX and Swing there are only two threads to be concerned with – the Swing dispatch thread and the JavaFX application thread – both of which should be managed by the respective underlying frameworks and you don’t need to explicitly close. You don’t need any other threads unless you are trying to do something which should not execute on either of those threads (such as a highly CPU intensive task or a remote I/O) – which from your sample code would not be appear to be the case.
Unless you have a specific need for such a thing, such a solution would likely further complicate your situation than improve it.
If you don’t keep a reference to any of the resources in the related jfxpanel, then the Java Virtual Machine can garbage collect the jfxpanel and and resources associated with it – this is just standard Java garbage collection technology, nothing special here.
Sounds like a bad idea (the main thread in Java terms is the thread used to launch the Java’s main function and is not involved in GUI programming at all). You probably want to submit your runnable refresh request via
Platform.runLater()so that it will be executed on the JavaFX application thread.You have a JavaFX JFXPanel in each swing tab and each swing tab knows which JFXPanel it has, so when you invoke Platform.runLater to refresh the specific panel, pass a (final) reference to the JFXPanel to be used. Here is some psuedo-code in no language whatsoever to illustrate the concept:
In essence I think you are correct here, I’ll just rewrite your question to clarify some of the terminology – let’s say it’s a swing button and on performing an action on the swing button, you make a call to
Platform.runLater, then the code in the runLater call will be eventually be executed on the JavaFX application thread.Other questions I cannot answer as I am not fluent enough in Scala to provide a reasonable answer.
Honestly, if you are just starting GUI building, then my unsolicited advice would be to use Java rather than Scala and stick with either Swing or JavaFX, but not mix it all together until you are really comfortable with the GUI building process – otherwise there are just way too many traps and pitfalls you may encounter during the integration that few will be able to assist you with.