【问题标题】:Java Mouse Listener error with UIManager SetLookAndFeelUIManager SetLookAndFeel 的 Java 鼠标侦听器错误
【发布时间】:2021-03-05 13:47:22
【问题描述】:

下面的代码显示了一个JFrame、一个JMenu和一个[自定义]JPanel

我通过调用方法 UIManager.setLookAndFeel 将外观 (LAF) 设置为 Windows LAF

我用鼠标单击JMenu,然后将鼠标移到[自定义]JPanel 上——此时菜单仍然可见。然后我再次单击鼠标,我的[自定义]JPanel 上的MouseListenermousePressed 方法不会被调用,即使mouseReleased 方法会调用。

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

我该如何解决这个问题?

以下是两个类:MListenPanelMListen 类声明了一个 main 方法,因此您可以启动该类。然后您可以执行上述操作来重现该行为。 Panel 类是我自定义的 JPanel

如果鼠标位于Panel 上,我希望每次按下鼠标时都会调用MouseListener 中的Panel 类中的mousePressed 方法。

  • MListen.java
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();  
            }  
        });  
    }

}
  • Panel.java
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,控制台不会显示“Press”。

谢谢!

  • 编辑 我需要 UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); 我可以在不删除它的情况下修复它吗? 我也需要第一次使用 MousePressed

【问题讨论】:

  • @matt:当 MouseListener 不需要焦点时,为什么会是“焦点问题”?
  • @HovercraftFullOfEels 我认为问题是,我点击菜单,然后点击我的 jpanel,它错过了按下的鼠标。然后他们得到一个错误,因为鼠标按下将被跳过。我几乎期待这种行为。如果显示菜单,则单击 jpanel。我真的不想发生任何事情。
  • 您是否声称它在您不UIManager.setLookAndFeel 时按预期工作?
  • 是的,我尝试删除它并且它有效。
  • “我尝试删除它,它成功了” 提示:添加@matt(或任何人,@ 很重要)到 通知新评论的人。

标签: java swing mouselistener uimanager


【解决方案1】:

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

这可以添加到您的 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 事件并调用该方法。

这是很好的调试代码,但不适合在您的项目中找到。

【讨论】:

  • 我需要 UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");我可以在不删除它的情况下修复它吗? 这是我需要的 setLookAndFeel。是否可以使用它并在第一次点击时检测鼠标按下?
  • @user15329314 我明白你在追求什么,我只是把它作为一个替代示例,因为 Windows LAF 在 OSX 上不可用。我想问题是“鼠标按下去哪里”。
  • 是的,我需要 JPanel 上的点击位置。是否有可能在第一次点击时获得位置?
  • setLookAndFeel 应该使用什么?示例中的 setLookAndFeel 在我的 PC 上看起来很糟糕(我不知道在每台 PC 上看起来是否都一样)
  • @user15329314 我用实际答案更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-19
  • 1970-01-01
  • 2011-12-18
相关资源
最近更新 更多