JFrame 中的 JavaFX 菜单 [英] JavaFX Menu in JFrame

查看:21
本文介绍了JFrame 中的 JavaFX 菜单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to use JavaFX Menu in JFrame. I embedded it using JFXPanel and it is visible in the JFrame. BUT, the problem is, MenuItems don't respond to mouse. I can click the Menu, but not the MenuItems. If i select the MenuItem using keyboard and hit enter, it works. (MenuItems don't get highlighted when i hover mouse over them)

注意:我没有遇到事件问题.单击菜单项下方的组件.

NOTE: I'm not having problem with Events. The click goes on component BELOW the menuItem.

此外,当 Swing 组件被聚焦然后我想点击菜单时,它需要点击 2 次.第一次点击只聚焦JFXPanel

Also, when the swing component is focused and then i want to click on the menu, it needs 2 clicks. First click only focuses the 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) {

    }

}

推荐答案

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

The requestFocus() method call, in the processMouseEvent() method of the JFXPanel class, is sent to the EventQueue and handled asynchronously and thus the click is not considered (due to lack of focus in the FX component).

将点击级联到底层菜单项,当 FXPanel 进入焦点时,应该再次触发相同的鼠标点击.

To cascade the click to the underlying menu item, the same mouse click should be fired again when the FXPanel comes into focus.

这样做,

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

  • Extend the JFXPanel Class and create your own CustomeJFXPanel (CustomJFXPanel extends JFXPanel).
  • Override the processMouseEvent(MouseEvent e) method as below.

@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() 类.

  • Replace JFXPanel() class by your new CustomJFXPanel() class.

    这是在 JDK9 中修复的.

    This is fixed in JDK9.

    (从其他来源收集)

    这篇关于JFrame 中的 JavaFX 菜单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆