I have an issue where Swing (in Java 1.6, Windows) doesn't seem to trigger mouseEntered and mouseExited events the way I want it to. I have an application where I wish to have a number of JPanels stacked vertically in a JScrollPane, and that they should be highlighted with a different colour when the mouse is over them. Simple enough problem, but whenever I scroll using the mouse wheel, it doesn't quite behave.
I have made a sample application to illustrate my problem (code found below). The images below are from that one, not the "real" application.
When I hold the mouse cursor over the edge of a panel, it's highlighted correctly. Now, when I use the mouse wheel to scroll down, I expect the cursor to be over box B, and the proper mouseEntered/mouseExited events to be triggered so that A becomes white and B becomes red.
(source: perp.se)
(source: perp.se)
However, that doesn't seem to happen.
Now, B becomes highlighted if I trigger another mouse event, be it "move 1 pixel", "click a button" or "scroll another step". Knowing this, I could perhaps solve it in a hackish way, but I'd rather not if there's a proper solution.
So basically what I'm wondering is if this is to be regarded as a bug in Swing, or am I just doing things wrong?
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
public class ScrollTest extends JFrame {
public static class LetterPanel extends JPanel {
private static final Font BIG_FONT = new Font(Font.MONOSPACED, Font.BOLD, 24);
public LetterPanel(String text) {
setBackground(Color.WHITE);
setBorder(BorderFactory.createLineBorder(Color.BLACK));
addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
setBackground(Color.RED);
}
@Override
public void mouseExited(MouseEvent e) {
setBackground(Color.WHITE);
}
});
setLayout(new GridLayout(1, 1));
setPreferredSize(new Dimension(-1, 50));
JLabel label = new JLabel(text, SwingConstants.CENTER);
label.setFont(BIG_FONT);
add(label);
}
}
public ScrollTest() {
setLayout(new GridLayout(1, 1));
setSize(400, 400);
JPanel base = new JPanel();
JScrollPane jsp = new JScrollPane(base);
jsp.getVerticalScrollBar().setUnitIncrement(16);
add(jsp);
base.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridheight = 1;
gbc.gridwidth = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(0, 0, 10, 0);
gbc.weightx = 1.0;
for (char c = 'A'; c <= 'Z'; c++) {
base.add(new LetterPanel(String.valueOf(c)), gbc);
gbc.gridy++;
}
}
public static void main(String[] args) {
final JFrame f = new ScrollTest();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
f.setVisible(true);
}
});
}
}