2016-07-22 28 views
2

Ich habe eine Frage zu benutzerdefinierten Tabkomponenten in Swing.JTabbedPane TabComponent Standardregisterkartenhervorhebung

Der folgende Code 3 benutzerdefinierte Registerkarte Komponenten hinzufügen:

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); 
    } 
} 

das Problem ist jetzt, dass das Standard-Tab Verhalten nicht mehr funktioniert. Wenn Sie die Maus über eine Registerkarte bewegen, wird sie automatisch hervorgehoben, indem Sie die Hintergrundfarbe ändern. aber sobald die JTextField ist, registriert die Registerkarte höchstwahrscheinlich eine mouseExited Event und stoppt die Hervorhebung der Registerkarte. Die Registerkarte wird also flackern, wenn Sie mit der Maus über die Registerkarte fahren.

meine Frage ist jetzt: Gibt es eine Möglichkeit (ohne einen neuen Hervorhebungsmechanismus zu implementieren), um die Registerkarte hervorzuheben, wo die benutzerdefinierte tabComponent befindet?

+1

Durch die Hervorhebung, bekommen der Fokus? –

+0

@TamasRev: Nein. Es könnte spezifisch für Nimbus LAF sein. Ich bin mir nicht sicher, wie sich die anderen LAFs in diesem Bereich verhalten. Die Registerkarten können sich in verschiedenen Zuständen befinden (zumindest so scheint es als einfacher Benutzer). fokussierte Maus außerhalb der Registerkartenregion (Farbe 1), fokussierte Maus innerhalb der Registerkartenregion (Farbe 2), unfokussierte Maus außerhalb der Registerkartenregion (Farbe 3), unfokussierte Maus innerhalb der Registerkartenregion (Farbe 4). Was mit der Markierung hervorgehoben wird, ist, wenn der Benutzer den Cursor über eine Registerkarte bewegt, die die Farbe der Registerkarte ändert. Mit einer benutzerdefinierten tabComponent wird es etwas flackern, wenn Sie die Maus über die Komponente bewegen. –

Antwort

2
  • Hier ist mein Versuch:
    • eine JLayer Mit dem MouseMotionEvent aus den Registerkarten an die Mutter JTabbedPane Versandfertig: Sie meinen
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)); 
    } 
} 
+0

Vielen Dank für Ihre Anfrage. Es funktioniert im Beispiel. Leider arbeite ich mit einer viel komplexeren Anwendung und es kann nicht so einfach integriert werden. Wie auch immer, der Teil, der die Magie macht, nach der ich gesucht habe, ist in deiner Methode 'dispatchEvent (MouseEvent e)'. Wenn ich den ganzen JLayer Teil ignoriere und einfach die 'dispatchEvent' Methode benutze, kann ich leicht mit dem JTextField arbeiten. Leider habe ich eine benutzerdefinierte Komponente (anstelle der JButton), die nicht funktioniert mit dem Code beim Übergeben der benutzerdefinierten Komponenten MouseEvent an die 'dispatchEvent?' Methode –

+0

Teil # 2: Der einzige Unterschied, den ich sehen kann (bei der Verwendung ' system.out.println 'mit' tgt', 'src' und' event', dass tgt einen etwas anderen Wert enthält von: 'javax.swing.JTabbedPane [, 0,0,1024x800, invalid, layout = ...'. Der Unterschied ist das Schlüsselwort "ungültig", aber ich muss zugeben, ich habe keine Ahnung, was falsch ist und warum es nicht funktioniert. –