Окно Java Swing может быть легко интегрировано в приложение C ++ (в Windows) с помощью класса WEmbeddedFrame:
// (1)
SwingUtilities.invokeLater(() -> {
try {
WEmbeddedFrame meinJFrame = new WEmbeddedFrame(hwndParentFromCppApplication);
meinJFrame.add(... panel ...);
...
meinJFrame.setVisible(true);
}
catch (...) {}
});
Кажется, что он работает гладко, хотя родительский HWND происходит из другого процесса. (Это потому, что инженеры Java могут манипулировать бензопилами: http://blogs.msdn.com/b/oldnewthing/archive/2013/04/12/10410454.aspx 🙂
Насколько я мог судить, для того, чтобы поместить JavaFX Stage в собственное родительское окно, возможен только косвенный способ с объектом JFXPanel, заключенным в 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 (...) {}
});
Но у этого решения есть два серьезных недостатка:
Сцена мерцает при наведении на нее мыши.
Элементы комбинированного списка и пункты меню размещаются в неправильной позиции после перемещения родительского окна.
Я также попытался поместить сцену в окно 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();
Это показывает только черный прямоугольник. Если я раскомментирую fxstage.show (), сцена будет открыта как окно верхнего уровня, а не внутри апплета.
В источниках JavaFX я нашел класс com.sun.javafx.stage.EmbeddedWindow. Звучит многообещающе, но как мне это использовать? Соответственно Как создать необходимую реализацию HostInterface?
Знаете ли вы, как поместить этап JavaFX в окно Windows C ++?
Спасибо заранее!
С уважением
Wolfgang
Основываясь на (2), я нашел решение после нескольких дней отладки внутри исходного кода JavaFX.
Но у меня все еще есть две проблемы:
(4) Я не могу получить объект javafx.stage.Window из JXPanel, который можно использовать в качестве окна владельца, например, для FileChooser. Следующий код возвращает внутренне используемый объект Stage. Но при использовании в качестве владельца он не блокирует дочерние окна.
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) При открытии FileChooser (owner = null) в поток пользовательского интерфейса выдается исключение. В настоящее время я игнорирую исключение, потому что оно ничего не вредит.
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)