A Java Swing window can be easily integrated into a C++ application (on Windows) by using the WEmbeddedFrame class:
// (1)
SwingUtilities.invokeLater(() -> {
try {
WEmbeddedFrame meinJFrame = new WEmbeddedFrame(hwndParentFromCppApplication);
meinJFrame.add(... panel ...);
...
meinJFrame.setVisible(true);
}
catch (...) {}
});
It seems to work smoothly, even though the parent HWND comes from a different process. (This is because the Java engineers are able to juggle chainsaws: http://blogs.msdn.com/b/oldnewthing/archive/2013/04/12/10410454.aspx :-)
As far as I could investigate, in order to put a JavaFX Stage into a native parent window, only an indirect way is possible with JFXPanel object wrapped into a Swing WEmbeddedFrame.
// (2)
Platform.runLater(() -> {
try {
WEmbeddedFrame frame = new WEmbeddedFrame(hwndParentFromCppApplication);
final JFXPanel fxPanel = new JFXPanel();
frame.add(fxPanel);
frame.setVisible(true);
Scene scene = ...
fxPanel.setScene(scene);
frame.show();
} catch (...) {}
});
But this solution has two serious disadvantages:
The scene is flickering when moving the mouse over it.
The combobox items and menu items are placed at the wrong position after the parent window has been moved.
I also tried to put the Stage into an AppletWindow:
// (3)
Stage fxstage = new Stage();
fxstage.initStyle(StageStyle.UNDECORATED);
fxstage.setScene(scene);
AppletWindow appw = tk.createAppletWindow(hwndParentFromCppApplication, "");
appw.setStageOnTop(fxstage);
appw.setPosition(0, 0);
appw.setSize(100, 100);
appw.setVisible(true);
// fxstage.show();
This shows only a black rectangle. If I uncomment fxstage.show(), the stage is opened as a toplevel window - not inside the applet.
In the JavaFX sources, I found the class com.sun.javafx.stage.EmbeddedWindow. It sounds promising, but how do I use it? Resp. how do I construct the required HostInterface implementation?
Do you know how to put a JavaFX stage into a Windows C++ window?
Many thanks in advance!
Regards Wolfgang
Based on (2), I found a solution after spending days with debugging inside JavaFX source.
But I still got two problems:
(4) I cannot get a javafx.stage.Window object from the JXPanel which can be used as an owner window e.g. for the FileChooser. The following code returns the internally used Stage object. But when used as an owner, it does not block the child windows.
public Window getWindow() {
try {
Class<?> clazz = fxPanel.getClass().getSuperclass();
Field field = clazz.getDeclaredField("stage");
field.setAccessible(true);
Window w = (Window) field.get(fxPanel);
return w;
} catch (Throwable e) {
throw new IllegalStateException("Cannot obtain JavaFX window.");
}
(5) When opening a FileChooser (owner=null) an exception is thrown in the UI thread. Currently, I ignore the exception because it does not harm anything.
Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: null source
at java.util.EventObject.<init>(EventObject.java:56)
at java.awt.AWTEvent.<init>(AWTEvent.java:337)
at sun.awt.UngrabEvent.<init>(UngrabEvent.java:48)
...
at com.sun.javafx.stage.WindowPeerListener.focusUngrab(WindowPeerListener.java:105)
...
at com.sun.javafx.tk.quantum.EmbeddedStage.focusUngrab(EmbeddedStage.java:252)
...
at com.sun.javafx.tk.quantum.QuantumToolkit.showFileChooser(QuantumToolkit.java:1421)
at javafx.stage.FileChooser.showDialog(FileChooser.java:416)
at javafx.stage.FileChooser.showOpenMultipleDialog(FileChooser.java:373)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With