【问题标题】:JavaFX Menu in JFrameJFrame 中的 JavaFX 菜单
【发布时间】:2014-11-30 06:01:17
【问题描述】:

我想在 JFrame 中使用 JavaFX 菜单。我使用 JFXPanel 嵌入了它,它在 JFrame 中可见。但是,问题是,MenuItems 不响应鼠标。我可以单击菜单,但不能单击 MenuItems。 如果我使用键盘选择 MenuItem 并按 Enter,它可以工作。 (当我将鼠标悬停在菜单项上时,它们不会突出显示)

注意:我对事件没有任何问题。点击菜单项下方的组件。

另外,当 Swing 组件获得焦点然后我想单击菜单时,它需要单击 2 次。第一次点击只关注 JFXPanel

package notepad;

import java.awt.BorderLayout;
import java.io.IOException;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class Notepad {

JFrame frame;
JFXPanel panel;
private void initSwing()
{
    frame = new JFrame();
    panel= new JFXPanel();

    frame.setSize(1024,768);
    frame.setLayout(new BorderLayout());
    frame.add(panel, BorderLayout.NORTH);
    Platform.runLater(() -> initFX(panel));

    frame.add(new JTextArea(), BorderLayout.CENTER);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}
private void initFX(JFXPanel jfxPanel) {
    try {
        Parent root = FXMLLoader.load(getClass().getResource("FXBars.fxml"));
        Scene scene = new Scene(root);


        jfxPanel.setScene(scene);
    } catch (IOException exc) {
        exc.printStackTrace();
        System.exit(1);
    }
}
public static void main(String[] args) {
    Notepad test = new Notepad();
    SwingUtilities.invokeLater(() -> test.initSwing() );
    }

}

FXML 文件:

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

<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.Button?>

<MenuBar xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="notepad.FXBarsController">
   <menus>
      <Menu mnemonicParsing="false" text="File">
         <items>
            <MenuItem mnemonicParsing="false" onAction="#menuClose" 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>

FXML 控制器:

package notepad;

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


public class FXBarsController implements Initializable {

    @FXML
    private void menuClose()
    {
        System.out.println("CLOSE");
    }

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

    }

}

【问题讨论】:

    标签: java swing menu javafx


    【解决方案1】:

    JFXPanel 类的 processMouseEvent() 方法中的 requestFocus() 方法调用被发送到 EventQueue 并异步处理,因此不考虑单击(由于 FX 组件中缺少焦点)。

    为了将点击级联到底层菜单项,当 FXPanel 成为焦点时,应再次触发相同的鼠标点击。

    这样做,

    • 扩展 JFXPanel 类并创建您自己的 CustomeJFXPanel(CustomJFXPanel 扩展 JFXPanel)。
    • 如下重写 processMouseEvent(MouseEvent e) 方法。

      @Override        
      protected void processMouseEvent(MouseEvent e) {        
          try {       
              if ((e.getID() == MouseEvent.MOUSE_PRESSED)&& (e.getButton() == MouseEvent.BUTTON1)) {       
                  if (!hasFocus()) {       
                      requestFocus();        
                      AppContext context = SunToolkit.targetToAppContext(this);        
                      if (context != null) {        
                          SunToolkit.postEvent(context, e);        
                      }        
                  }       
              }        
          } catch (Exception ex) {        
              //DO SOMETHING        
          }        
          super.processMouseEvent(e);        
      }
      
    • 用新的 CustomJFXPanel() 类替换 JFXPanel() 类。

    这在 JDK9 中已修复。

    (从其他来源收集)

    【讨论】:

      【解决方案2】:

      这就是它的基本工作方式。

      import javafx.application.Platform;
      import javafx.embed.swing.JFXPanel;
      import javafx.event.ActionEvent;
      import javafx.event.EventHandler;
      import javafx.scene.Group;
      import javafx.scene.Scene;
      import javafx.scene.control.Menu;
      import javafx.scene.control.MenuBar;
      import javafx.scene.control.MenuItem;
      
      import javax.swing.JFrame;
      import javax.swing.SwingUtilities;
      
      public class TestSwingIntegration {
      
          private static void initAndShowGUI() {
      
              JFrame frame = new JFrame("FX");
              final JFXPanel fxPanel = new JFXPanel();
              frame.add(fxPanel);
              frame.setVisible(true);
              frame.setSize(800, 600);
      
              Platform.runLater(new Runnable() {
                  @Override
                  public void run() {
                      initFX(fxPanel);
                  }
              });
          }
      
          private static void initFX(JFXPanel fxPanel) {
      
              Group root = new Group();
      
              MenuBar menuBar = new MenuBar();
              Menu menuFile = new Menu("File");
              MenuItem miClose = new MenuItem("Close");
              miClose.setOnAction(new EventHandler<ActionEvent>() {
                  public void handle(ActionEvent t) {
                      System.out.println( "Close pressed");
                  }
              });      
              menuFile.getItems().add( miClose);
      
              menuBar.getMenus().addAll(menuFile);
      
              root.getChildren().add( menuBar);
      
              Scene scene = new Scene(root, 200, 200);
              fxPanel.setScene(scene);
          }
      
          public static void main(String[] args) {
              SwingUtilities.invokeLater(new Runnable() {
                  @Override
                  public void run() {
                      initAndShowGUI();
                  }
              });
          }
      
      }
      

      点击文件->关闭,检查控制台输出。

      【讨论】:

      • 不,我对事件没有问题。它没有被点击。当我单击它时,单击转到菜单下方的组件。考虑记事本。我点击了 menuitem,但是点击了 textarea。
      • 发布代码来自 3 个文件,主要 java 文件,FXML 和 FXMLController
      猜你喜欢
      • 2017-01-09
      • 1970-01-01
      • 2018-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多