将JavaFX Stage嵌入到C ++ Windows应用程序中

时间:2014-10-13 18:08:04

标签: c++ windows javafx

使用WEmbeddedFrame类可以轻松地将Java Swing窗口集成到C ++应用程序中(在Windows上):

// (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(),则舞台将作为顶层窗口打开 - 而不是在applet中。

在JavaFX源代码中,我找到了类com.sun.javafx.stage.EmbeddedWindow。这听起来很有希望,但我该如何使用呢? RESP。如何构造所需的HostInterface实现?

您知道如何将JavaFX阶段放入Windows C ++窗口吗?

非常感谢提前!

此致 沃尔夫冈

1 个答案:

答案 0 :(得分:1)

基于(2),我在JavaFX源代码中花了几天调试后发现了一个解决方案。

  • 将JXPanel包装到JPanel中。这会停止闪烁。
  • 覆盖JXPanel.setCursor()并调用WEmbeddedFrame.setCursor()。否则,在JavaFX控件中更改游标无效。
  • 将scene.getWindow()。setX(),Y,Width,Heigth设置为本机容器窗口的GetClientRect()。这会在正确的位置显示组合框和菜单项。

但我仍有两个问题:

(4)我无法从JXPanel获取javafx.stage.Window对象,该对象可用作所有者窗口,例如对于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)时,UI线程中会抛出异常。目前,我忽略了异常,因为它不会造成任何伤害。

    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)