有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

JFrame中的JavaFX菜单

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

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

另外,当swing组件被聚焦,然后我想点击菜单时,它需要点击两次。第一次单击仅聚焦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) {

    }

}

共 (1) 个答案

  1. # 1 楼答案

    JFXPanel类的ProcessMouseeEvent()方法中的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中是固定的

    (从另一个来源收集)