Tab component consuming mouse so tabs won't change
I have a problem that when I add a mouse listener to a component that is used as a tab, I can't switch tabs.
This demonstrates the problem:
import javax.swing.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
public class JTabBug {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JTabbedPane jTabbedPane = new JTabbedPane();
jTabbedPane.addTab("Red", new JLabel("Roses"));
jTabbedPane.addTab("Blue", new JLabel("Skies"));
jTabbedPane.addTab("Green", new JLabel("Grass"));
for (int i = 0; i < jTabbedPane.getTabCount(); i++) {
JLabel tabComponent = new JLabel(jTabbedP开发者_开发问答ane.getTitleAt(i));
tabComponent.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
System.out.println("dragging");
}
});
jTabbedPane.setTabComponentAt(i, tabComponent);
}
JFrame jFrame = new JFrame("Testing");
jFrame.add(jTabbedPane);
jFrame.setSize(400, 500);
jFrame.setVisible(true);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
}
dragging is printed out as expected but you can't change tabs.
Override the contains
method of your tab component (a JLabel in your case) to return false.
public boolean contains(int x, int y)
{
return false;
}
This seems to work: Notice that I'm getting the JLabel that was added, not creating a new one to add again.
import javax.swing.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
public class JTabBug {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JTabbedPane jTabbedPane = new JTabbedPane();
jTabbedPane.addTab("Red", new JLabel("Roses"));
jTabbedPane.addTab("Blue", new JLabel("Skies"));
jTabbedPane.addTab("Green", new JLabel("Grass"));
for (int i = 0; i < jTabbedPane.getTabCount(); i++) {
JLabel tabComponent = (JLabel)jTabbedPane.getComponent(i);
tabComponent.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
System.out.println("dragging");
}
});
}
JFrame jFrame = new JFrame("Testing");
jFrame.add(jTabbedPane);
jFrame.setSize(400, 500);
jFrame.setVisible(true);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
}
I don't think this is a bug, as it's doing what I would expect. You're creating a new component for the tab (a JLabel), attaching a motion listener to it, and then setting that as the tab. You're not adding a mouse click listener to the label that would cause the tabs to change, so I wouldn't expect this to be there. The original tab component handles this mouse click event, so if you can get access to that component, try copying it if you can (or just get access to that component and add the mouse motion adapter). If this isn't possible, just handle the click event yourself.
It looks like mouse events don't change the selection of the tab if the new tab component has another listener. Not sure why this is because the new label tab component works without the mouse motion listener. If you add another mouse listener to change the selection:
final int index = i;
tabComponent.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
jTabbedPane.setSelectedIndex(index);
}
});
You get the desired result, but it seems like this would be a strange workaround.
My solution is a bit more elaborated then jzd's, I didn't know that it could be done so cleanly. I like your solution it thought me something new. Thanks, jzd for that.
public class JTabBug
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
final JTabbedPane jTabbedPane = new JTabbedPane();
jTabbedPane.addTab("Red", new JLabel("Roses"));
jTabbedPane.addTab("Blue", new JLabel("Skies"));
jTabbedPane.addTab("Green", new JLabel("Grass"));
for(int i = 0; i < jTabbedPane.getTabCount(); i++)
{
final JLabel tabComponent = new JLabel(jTabbedPane.getTitleAt(i));
tabComponent.addMouseMotionListener(new MouseMotionAdapter()
{
@Override
public void mouseDragged(MouseEvent e)
{
System.out.println("tabComponent dragging");
}
});
jTabbedPane.setTabPlacement(JTabbedPane.LEFT);
tabComponent.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent e)
{
int x = tabComponent.getLocationOnScreen().x - jTabbedPane.getLocationOnScreen().x;
int y = tabComponent.getLocationOnScreen().y - jTabbedPane.getLocationOnScreen().y;
MouseEvent me = new MouseEvent(
(JLabel)e.getSource(),
e.getID(), e.getWhen(), e.getModifiers(),
x, y,
e.getLocationOnScreen(). x, e.getLocationOnScreen().y,
e.getClickCount(), e.isPopupTrigger(),
e.getButton());
jTabbedPane.getMouseListeners()[0].mousePressed(me);
System.out.println("tabComponent mousePressed e="+e);
}
});
jTabbedPane.setTabComponentAt(i, tabComponent);
}
JFrame jFrame = new JFrame("Testing");
jFrame.add(jTabbedPane);
jFrame.setSize(400, 500);
jFrame.setVisible(true);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
}
Enjoy, Boro
精彩评论