Reputation: 78
I have a question regarding custom tab components in swing.
The following code will add 3 custom tab components:
public class TabbedExample extends JPanel {
public static void main(String... args) {
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
createUI();
}
}
}
public static void createUI() {
try {
for(LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch(Exception e) {}
JFrame frame = new JFrame("Tab Test");
frame.setMinimumSize(new Dimension(256,200));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().add(new TabbedExample());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public TabbedExample() {
super(new BorderLayout());
JTabbedPane pane = new JTabbedPane();
pane.addTab("tmp", new JTextField());
pane.addTab("tmp", new JTextField());
pane.addTab("tmp", new JTextField());
for(int i = 0; i < 3; i++) {
JPanel tabPanel = new JPanel();
tabPanel.setBackground(new Color(0,0,0,0));
tabPanel.setLayout(new BoxLayout(tabPanel, BoxLayout.X_AXIS));
JTextField textField = new JTextField("Tab " + i);
textField.setOpaque(false);
textField.setBackground(new Color(0,0,0,0));
textField.setBorder(new EmptyBorder(0,0,0,0));
tabPanel.add(label);
tabPanel.add(new JButton(Integer.toString(i)));
pane.setTabComponentAt(i, tabPanel);
}
add(pane, BorderLayout.CENTER);
}
}
the problem now is that the default tab behaviour stops working. normally, when you move your mouse over a tab, it automagically gets highlight by changing the background color. but as soon as the JTextField
is hit, the tab most likely registers a mouseExited Event
and stops the highlighting of the tab. so the tab will flicker when you move your mouse over the tab.
my question now is: Is there a way (without implementing a new highlighting mechanism) to highlight the tab, where the custom tabComponent is located?
Upvotes: 2
Views: 426
Reputation: 9833
JLayer
to dispatch the MouseMotionEvent
from the tabs to the parent JTabbedPane
:import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.*;
public class TabbedExample2 extends JPanel {
public static void main(String... args) {
EventQueue.invokeLater(() -> {
createUI();
});
}
public static void createUI() {
try {
for (UIManager.LookAndFeelInfo laf: UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(laf.getName())) {
UIManager.setLookAndFeel(laf.getClassName());
}
}
} catch (Exception e) {
e.printStackTrace();
}
JFrame frame = new JFrame("Tab Test");
frame.setMinimumSize(new Dimension(256, 200));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().add(new TabbedExample2());
frame.setSize(320, 240);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public TabbedExample2() {
super(new BorderLayout());
JTabbedPane pane = new JTabbedPane();
pane.addTab("tmp", new JTextField(16));
pane.addTab("tmp", new JTextField(16));
pane.addTab("tmp", new JTextField(16));
for (int i = 0; i < 3; i++) {
JPanel tabPanel = new JPanel();
tabPanel.setOpaque(false);
//tabPanel.setBackground(new Color(0,0,0,0));
tabPanel.setLayout(new BoxLayout(tabPanel, BoxLayout.X_AXIS));
JTextField textField = new JTextField("Tab " + i);
//textField.setBackground(new Color(0,0,0,0));
//textField.setBorder(new EmptyBorder(0,0,0,0));
//tabPanel.add(label); //???
tabPanel.add(textField);
tabPanel.add(new JButton(Integer.toString(i)));
pane.setTabComponentAt(
i, new JLayer<JPanel>(tabPanel, new DispatchEventLayerUI()));
}
add(pane);
}
}
class DispatchEventLayerUI extends LayerUI<JPanel> {
@Override
public void installUI(JComponent c) {
super.installUI(c);
if (c instanceof JLayer) {
((JLayer) c).setLayerEventMask(AWTEvent.MOUSE_MOTION_EVENT_MASK);
//TEST:
//((JLayer) c).setLayerEventMask(
// AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
}
}
@Override
public void uninstallUI(JComponent c) {
if (c instanceof JLayer) {
((JLayer) c).setLayerEventMask(0);
}
super.uninstallUI(c);
}
// //TEST:
// @Override
// protected void processMouseEvent(MouseEvent e, JLayer<? extends JPanel> l) {
// dispatchEvent(e);
// }
@Override
protected void processMouseMotionEvent(MouseEvent e, JLayer<? extends JPanel> l) {
dispatchEvent(e);
}
private void dispatchEvent(MouseEvent e) {
Component src = e.getComponent();
Container tgt = SwingUtilities.getAncestorOfClass(JTabbedPane.class, src);
tgt.dispatchEvent(SwingUtilities.convertMouseEvent(src, e, tgt));
}
}
Upvotes: 2