MenuItem动作事件未被触发

时间:2018-04-19 17:42:04

标签: swing javafx

我有一个使用JDesktopPane的旧Java Swing应用程序。我知道JavaFX并不支持这一点,并且MDI总体上不受欢迎。无论我想看看JavaFX中的类似应用程序是如何实现的,并且遇到了我在这里问的问题。

简而言之,我有一个包含带有JDesktopPane的SwingNode的JavaFX应用程序。在该桌面窗格中,我打开一个加载JavaFX场景的JInternalFrame。

问题是JInternalFrame场景包含一个菜单栏。菜单栏中的MenuItems可以使用键盘激活,但在鼠标事件中不会激活。

我认为鼠标事件没有进入JavaFX组件,而是可能转到Swing线程。我已经尝试过无数种方法来解决这个问题(例如Spark History Server)但是没有运气。

代码如下。任何建议都表示赞赏。

Test.java

package test;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Test extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("MainScene.fxml"));

        Scene scene = new Scene(root);

        stage.setScene(scene);
        stage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

MainScene.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>

<AnchorPane id="AnchorPane" prefHeight="508.0" prefWidth="665.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="test.MainSceneController">
    <children>
      <BorderPane fx:id="borderPane" prefHeight="200.0" prefWidth="320.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
         <top>
            <MenuBar BorderPane.alignment="CENTER">
              <menus>
                <Menu mnemonicParsing="false" text="File">
                  <items>
                    <MenuItem mnemonicParsing="false" onAction="#handleAddInternalFrameAction" text="Add internal frame" />
                  </items>
                </Menu>
                <Menu mnemonicParsing="false" text="Edit">
                  <items>
                    <MenuItem mnemonicParsing="false" text="Delete" />
                  </items>
                </Menu>
                <Menu mnemonicParsing="false" text="Help">
                  <items>
                    <MenuItem mnemonicParsing="false" text="About" />
                  </items>
                </Menu>
              </menus>
            </MenuBar>
         </top>
      </BorderPane>
    </children>
</AnchorPane>

MainSceneController.java

package test;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.embed.swing.SwingNode;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.layout.BorderPane;
import javax.swing.JDesktopPane;
import javax.swing.SwingUtilities;

public class MainSceneController implements Initializable {

    JDesktopPane desktopPane = new JDesktopPane();

    @FXML
    BorderPane borderPane;

    @FXML
    private void handleAddInternalFrameAction(ActionEvent event) {        
        InternalFrame internalFrame = new InternalFrame();

        desktopPane.add(internalFrame);

        internalFrame.setVisible(true);
    }


    @Override
    public void initialize(URL url, ResourceBundle rb) {        
        final SwingNode swingNode = new SwingNode();

        SwingUtilities.invokeLater(() -> {
            swingNode.setContent(desktopPane);
        });

        borderPane.setCenter(swingNode);  
    }    

}

InternalFrame.java

package test;

import java.awt.Dimension;
import java.io.IOException;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javax.swing.JInternalFrame;

public class InternalFrame extends JInternalFrame {

    public InternalFrame() {        
        setTitle("InternalFrameScene.fxml");                      
        setResizable(true);
        setSize(300, 300);
        setPreferredSize(new Dimension(300, 300));

        JFXPanel jfxPanel = new JFXPanel();
        add(jfxPanel);

        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                try {
                    FXMLLoader fxmlLoader = new FXMLLoader(InternalFrame.class.getResource("InternalFrameScene.fxml"));

                    Scene scene = new Scene(fxmlLoader.load());

                    jfxPanel.setScene(scene);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }    

}

InternalFrameScene.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>

<AnchorPane fx:id="anchorPane" minHeight="400.0" minWidth="400.0" prefHeight="500.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="test.InternalFrameController">
   <children>
      <BorderPane fx:id="borderPane" prefHeight="500.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
         <top>
            <MenuBar fx:id="menuBar" BorderPane.alignment="CENTER">
              <menus>
                <Menu mnemonicParsing="false" text="File">
                  <items>
                    <MenuItem mnemonicParsing="false" onAction="#closeMenuItemAction" text="Close" />
                  </items>
                </Menu>
                <Menu mnemonicParsing="false" text="Edit">
                  <items>
                    <MenuItem mnemonicParsing="false" text="Delete" />
                  </items>
                </Menu>
                <Menu mnemonicParsing="false" text="Help">
                  <items>
                    <MenuItem mnemonicParsing="false" text="About" />
                  </items>
                </Menu>
              </menus>
            </MenuBar>
         </top>
      </BorderPane>
   </children>
</AnchorPane>

InternalFrameController.java

package test;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;

public class InternalFrameController implements Initializable {

    @FXML
    private void closeMenuItemAction(ActionEvent event) {
        System.out.println("closeMenuItemAction");
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {}

}

0 个答案:

没有答案