JTable HeaderRenderer mit System LookAndFeel (PLAF)

Ach, es ist schon ein Kreuz mit Plattform-Designs. Insbesondere mit Swing. Will man für Tabellen die Spaltenköpfe etwas optisch anpassen, aber zugleich das System-Design nicht verlieren, muss man ein paar kleine Tricks anwenden, die gar nicht mal so gut dokumentiert sind.

Hier mal ein Beispiel wie es für Windows 7 aussieht, wenn man des Standard-Renderer nutzt:

So sieht es aus, wenn man nach den üblichen Rezepten vorgeht und einen eigenen Renderer verwendet:

Sogar wenn man den original installierten Renderer (der durch das PLAF gesetzt wurde) aus dem JTableHeader nimmt und diesen ändert, wird man feststellen, dass die Tabellenköpfe trotzdem wie aus den 90′er Jahren aussehen. Ungefähr so wie alte Sportschuhe von den Fußballern aus derzeit. So etwas wäre aber sicherlich mit einem Fußballschuh Test nicht passiert.

Der eigentliche Grund ist, dass man i.d.R. es verpasst UI-Änderungen des UIManager an den Header-Renderer weiterzuleiten.

Generell ist es gut dem eigenen Renderer im Constructor den als Standard installierten Renderer mitzugeben, der von Java Swing sowieso gesetzt wird:

public class DBTableHeaderRenderer 
            extends DefaultTableCellRenderer 
            implements TableCellRenderer {
private final TableCellRenderer headerRendererUI;
public DBTableHeaderRenderer(TableCellRenderer headerRenderer) {
  this.headerRendererUI = headerRenderer;
}

Nun holt man in der getTableCellRendererComponent Methode aus dem headerRendererUI die Renderer-Komponente, die man anpassen möchte:

@Override
 public Component getTableCellRendererComponent(
   JTable table, Object value,
   boolean isSelected, boolean hasFocus, int row, int column) 
 {
   Component resUI = headerRendererUI
                    .getTableCellRendererComponent (table, value,
                                  isSelected, hasFocus, 
                                  row, column);
  if (resUI instanceof JLabel) {
    JLabel label = (JLabel) resUI;

Wenn man das debugged, stellt man fest, dass in resUI tatsächlich die UI-Komponente aus dem System-PLAF ist, aber trotzdem sieht es aus, als würden die Header wie in Windows 2000 gezeichnet.

Änderungen beim PLAF werden allen Komponenten via updateUI mitgeteilt. Im unseren Renderer können wir die Methode überschreiben und die Benachrichtigung an headerRendererUI delegieren:

 @Override
 public void updateUI() {
   TableCellRenderer tcr = headerRendererUI;
   if (tcr instanceof JComponent) {
     ((JComponent) tcr).updateUI();
   } else {
     super.updateUI();
   }
 }

Obwohl dies das exakt richtige Vorgehen ist, wird man beim nächsten Test sich die Haare raufen. Der Renderer sieht immer noch altbacken aus.

Wir müssen unseren Renderer noch mit einem Marker-Interface ausstatten, damit auch wirklich updateUI aufgerufen wird. Also muss die Klassen-Deklaration ergänzt werden:

public class DBTableHeaderRenderer 
       extends DefaultTableCellRenderer 
       implements TableCellRenderer, javax.swing.plaf.UIResource {

Mit dem UIRessource-Interface ist der Renderer nun endlich optisch auf Höhe der Zeit und man kann das JLabel nun nach eigenen Wünschen anpassen.

 

Dieser Beitrag wurde unter Uncategorized abgelegt und mit , , , , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.