Java UIManager SetLookAndFeel 的鼠标侦听器错误

Java Mouse Listener error with UIManager SetLookAndFeel

下面的代码显示 JFrameJMenu 以及 [自定义] JPanel

我通过调用方法 UIManager.setLookAndFeel

将外观 (LAF) 设置为 Windows LAF

我用鼠标单击 JMenu,然后将鼠标移到 [自定义] JPanel - 同时菜单仍然可见。然后我再次单击鼠标,我的 [custom] JPanel 上的 MouseListenermousePressed 方法没有被调用,即使 mouseReleased 方法调用了。

如果我没有明确设置 LAF,即如果我使用默认的 LAF,它工作正常。

我该如何解决这个问题?

下面有两个 class:MListenPanel。 Class MListen 声明了一个 main 方法,因此您可以启动那个 class。然后您可以执行上述操作来重现该行为。 Class Panel 是我的习惯 JPanel.

我希望在 class PanelMouseListenermousePressed 方法在每次按下鼠标时调用 [=] 24=].

package drawer.Main;
import javax.swing.*;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.*;

public class MListen extends JFrame{

    public MListen(){
        
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        setSize(800, 600);
        //setExtendedState(MAXIMIZED_BOTH);
        setLayout(new BorderLayout());
        getContentPane().setBackground(Color.WHITE);
        
        
        Panel panel = new Panel();
        JMenuBar bar = new JMenuBar();
        JMenu file = new JMenu("file");
        JMenuItem open = new JMenuItem("open");
        JButton b = new JButton("AB");
        file.add(b);
        
        bar.add(file);
        file.add(open);
        setJMenuBar(bar);
        
        add(panel, BorderLayout.CENTER);
        
        setVisible(true);
        
    }
    
    public static void main(String[] args){
        javax.swing.SwingUtilities.invokeLater(new Runnable() {  
              
            public void run() {
                try {
                    UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
                        | UnsupportedLookAndFeelException e) {
                    e.printStackTrace();
                }
                new MListen();  
            }  
        });  
    }

}
package drawer.Main;

import java.awt.*;
import java.awt.event.*;
import javax.swing.JPanel;

public class Panel extends JPanel implements MouseListener, MouseMotionListener{
    public float size;
    public Color color;
    public boolean DoDraw;

    public Panel(){
        addMouseListener(this);
        setFocusable(true);
        addMouseMotionListener(this);
        setBackground(Color.RED);
    }

    @Override
    public void mouseDragged(MouseEvent arg0) {
        //System.out.println("Drag");
        
    }

    @Override
    public void mouseMoved(MouseEvent arg0) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void mouseClicked(MouseEvent arg0) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void mouseEntered(MouseEvent arg0) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void mouseExited(MouseEvent arg0) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void mousePressed(MouseEvent arg0) {
        System.out.println("Press");
        // TODO Auto-generated method stub
        
    }

    @Override
    public void mouseReleased(MouseEvent arg0) {
        System.out.println("relese");
        // TODO Auto-generated method stub
        
    }
}

尝试 运行 点击红色 JPanel 上面的代码。控制台将显示“按下”。现在点击 JMenu 然后点击 JPanel 和“按下”将 而不是 显示在控制台中。

谢谢!

这是一个错误的答案,但它应该有效。您可以在委托之前捕获所有事件。

这可以添加到您的 JPanel 构造函数中。

long eventMask = AWTEvent.MOUSE_EVENT_MASK;
Toolkit.getDefaultToolkit().addAWTEventListener( new AWTEventListener() {
    public void eventDispatched(AWTEvent e){
                MouseEvent evt = (MouseEvent)e;
                if( evt.getSource() == this && evt.getId()==MouseEvent.MOUSE_PRESSED ){
                    this.mousePressed(evt);
                    evt.consume();
                }
    }
}, eventMask );

这会捕获所有鼠标事件,检查它们是否来自正确的面板,检查它是否是 mousePressed 事件并调用该方法。

这是用于调试的好代码,但在您的项目中不好找到。