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.

 

Veröffentlicht unter Uncategorized | Verschlagwortet mit , , , , | Hinterlasse einen Kommentar

JavaFXDev: NetBeans Platform with JavaFX 2.0ea

Hi!

Alan O’Leary shows in his blog a WebView integration in Swing. It is a not good documented feature, how to integrate JavaFX 2.0 controls into a swing application. But an integration is a main goal for the JavaFX 2.0 release.

As an enthusiastic NetBeans Platform/RCP developer and JavaFX partner, I work since two days to marriage JavaFX 2.0 and a NetBeans Platform Application. And yes, it works 🙂

I’ve created a maven based platform application with a special starter Main.class. I need to launch the JavaFX toolkit system before any other module bootstrapping. The solution here is based on the early access release through the JavaFX partner program. This “best practice” may change significantly between now and the final version. However, I’ll show only a concept, not compilable code.

The solution behind the bootstrapping a NetBeans Platform is based on a FAQ by Tom Wheeler. My Main.class is a JavaFX Application class – I need this Application instance to get rid of from invoke exceptions. The created Stage object by the Launcher can be ignored.

The Main class is in a standard Java archive. This JAR file and all the JavaFX files must be in the platform/core folder.

At runtime all the core-Libs are available to the whole NetBeans Platform modules (and plugins). For the compiler I need a special dependency to the runtime:

The system path depends on your project structure.

Now I can access all the JavaFX classes in a NetBeans module.

Please note, any scene construction needs to be build up in the JavaFX event queue thread. This is not the EventDispatcher-Thread from Swing!

My favorite call to jump in the JavaFX event thread is: Toolkit.getDefault().defer (Runnable) javafx.application.Platform.runLater (Runnable). But the Toolkit class is in a com.* package. IMHO in the future we get an official way to do this.

The creation of a WebView component is pretty similar to the sample from Alan. But I don’t need a stage object:

I’ve added some useful listeners. Please aware the switches between different threads (Swing and JavaFX).

The result is a beautiful NetBeans Platform application with an embedded JavaFX 2.0 WebView:

PS.: I like the Twitter message from Dean Riverson: “Ok, I call a moratorium on rotating and reflecting WebView…” (origin). –

I have to write 100 times:

Veröffentlicht unter Uncategorized | Verschlagwortet mit , , | Hinterlasse einen Kommentar