This is the code I am using to show the issue which I am facing in another project.
I am not getting any line like this if I use JScrollPane as a wrapper for panel2. Why? I want to click on JscrollPane and got event printed as following.
java.awt.event.MouseEvent[MOUSE_CLICKED,(800,469),absolute(808,499),button=1,modifiers=Button1,clickCount=1] on javax.swing.JPanel[,0,0,934x612,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=javax.swing.border.LineBorder@cc0e01,flags=9,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=880,height=630]]
If now I change
panel1.add(pane);
to
panel1.add(panel2);
Then the message above got printed.
public class LostMouseEvent {
public static void main(String[] args) {
new LostMouseEvent();
}
public LostMouseEvent() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
JScrollPane pane = new JScrollPane(panel2);
panel1.setPreferredSize(new Dimension(880, 630));
panel1.setBorder(BorderFactory.createLineBorder(Color.blue));
panel2.setPreferredSize(new Dimension(840, 610));
panel2.setBorder(BorderFactory.createLineBorder(Color.green));
panel1.add(pane);
frame.add(panel1);
frame.pack();
frame.setVisible(true);
frame.setSize(950, 650);
panel1.addMouseListener(new MyMouseListener());
}
});
}
private class MyMouseListener extends MouseAdapter {
@Override
public void mouseClicked (MouseEvent me) {
System.out.println(me);
}
}
}
UPD: In fact in my project there is more than just one panel2. Originally, I had panel1 and many panel2 inside. Then I wanted to wrap each panel2 with JScrollPane and started to face this problem.
I need to have only one MouseListener to minimize changes to the code.
setSize()
rather call pack()
before setting JFrame
visible.setPrefferedSize()
rather override getPrefferedSize()
Your code works as expected, it will only print the message if panel1
is clicked, note panel1
is behind JScrollPane
, thus anything outside the green border is panel1
. To make it work for both the JScrollpane
/panel2
and JPanel
/panel1
simply add the MouseListener
to BOTH of the required components:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class LostMouseEvent {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new LostMouseEvent();
}
});
}
public LostMouseEvent() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JPanel panel1 = new JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(880, 630);
}
};
JPanel panel2 = new JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(840, 610);
}
};
JScrollPane pane = new JScrollPane(panel2);
panel1.setBorder(BorderFactory.createLineBorder(Color.blue));
panel2.setBorder(BorderFactory.createLineBorder(Color.green));
panel1.add(pane);
frame.add(panel1);
MouseListener ml=new MyMouseListener();
//add mouse listener to panel1 and panel2
panel1.addMouseListener(ml);
panel2.addMouseListener(ml);
//alternatively add to pane
//pane.addMouseListener(ml);
frame.pack();
frame.setVisible(true);
}
});
}
private class MyMouseListener extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent me) {
System.out.println(me);
}
}
}
EDIT:
I personally would not recommend this, however,
To add a single listener to the JFrame
that will capture all MouseEvent
s use Toolkit
class and call addAWTEventListener
like so:
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent awte) {//all mouse events will be processed here you will have to check for the mouse events you are interested in
System.out.println(awte);
}
}, AWTEvent.MOUSE_EVENT_MASK);//for Mouse events only
UPDATE 1:
You could also add the MouseListener
to your JFrame
s glasspane via JFrame.getGlassPane().addMouseListener(ml)
dont forget to set the glasspane visible after setting JFrame
visible. This will allow you to only have to add a single Listener
. See here:
...
MouseListener ml = new MyMouseListener();
//add mouse listener to panel1 and panel2
//panel1.addMouseListener(ml);
//panel2.addMouseListener(ml);
//alternatively add to pane
//pane.addMouseListener(ml);
frame.getGlassPane().addMouseListener(ml);
frame.pack();
frame.setVisible(true);
frame.getGlassPane().setVisible(true);
...
UPADTE 2:
The main reason for you having the problem of the MouseEvent
getting lost in JScrollPane
is because its a bug. See here.
The work around shown is:
public Test()
{
setUI(new javax.swing.plaf.metal.MetalScrollPaneUI(){
public void installListeners(JScrollPane scrollPane){}
});
JPanel canvas = new JPanel();
canvas.add( new JLabel("Test") );
setViewportView( canvas );
setVisible(true);
}
MouseEvent lost in JScrollPane
answer is very / quite simple, be sure that there isn't something about lost events, nor with JScrollPane,
Swing JComponent can firing event only if is there added proper Listener
you not added MouseListener to second JPanel,
this JPanel is placed into parent JPanel, this parent has added MouseListener then firing mouseEvent, sure in your case only outside of Bounds of 2nd JPanel added to this container
then 2nd JPanel is deepestComponentAt, and not possible fire event without redispatch coordinates from parent to child
you can to redispatch event programatically too,
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With