The below code displays a JFrame
with a JMenu
and a [custom] JPanel
.
I set the look-and-feel (LAF) to Windows LAF by calling method UIManager.setLookAndFeel
I click on the JMenu
with the mouse and then I move the mouse onto the [custom] JPanel
– while the menu is still visible. Then I click the mouse again and the mousePressed
method of the MouseListener
on my [custom] JPanel
does not get called, even though the mouseReleased
method does.
If I do not explicitly set the LAF, i.e. if I use the default LAF, it works fine.
How can I fix this?
Below are two classes: MListen
and Panel
. Class MListen
declares a main
method, so you can launch that class. Then you can perform the actions described above to reproduce the behavior. Class Panel
is my custom JPanel
.
I want the mousePressed
method of the MouseListener
, in class Panel
to be called every time that the mouse is pressed if it is on the Panel
.
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
}
}
Try running the above code clicking on the red JPanel
. The console will display "Press". Now click on the JMenu
and then on the JPanel
and "Press" will not be displayed in the console.
Thanks!
Here is a bad answer, but it should work. You can capture all of the events before they're delegated.
This can be added to your JPanel constructor.
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 );
This captures all mouse events check that they original from the correct panel, checks if it is a mousePressed event and calls the method.
This is good code for debugging, but not good to find in your project.