JTable Header L&F

VitiumJava

Mitglied
Hallo Zusammen,

kleines Problem.

In meinem kleinen Programm setzte ich am Anfang,

Java:
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());


Des Weiteren habe ich eine JTable erstellt wo ich meinen eigenen Header mit
Java:
public class TableHeader extends JLabel implements TableCellRenderer { 

private static final long serialVersionUID = 6221428923597532143L;
	
	@Override
	public Component getTableCellRendererComponent(JTable table, Object value,
			boolean isSelected, boolean hasFocus, int row, int column) {
		
		JComponent c = null;
		if(value instanceof String) {
			c = new JLabel(value.toString());
            ((JLabel)c).setHorizontalAlignment(SwingConstants.CENTER);
		}
		
		c.setEnabled(true);
        c.setBorder(UIManager.getBorder("TableHeader.cellBorder"));
        c.setOpaque(true);

		return c;
	}

}

erstelle.

Nach dem einsetzen des Header in die JTable ist leider der System look and Feel in der Tablle bzw. Header der Tabelle nicht mehr vorhanden bzw, wie vorher.

Wie kann ich das L&F der Tabelle wieder auf System L&F setzten? Oder wie es vorher war? Danke.
 
Weist du warum es CellRenderer gibt? Weil es die Performance in den Keller jagen würde, wenn man für eine JTable mit 10000 Zellen auch 10000 Labels anlegen müsste. Der Sinn von einem Cell Renderer ist, dass man eben nur ein JLabel hat und Abbilder von ihm mit einem gewünschten Inhalt auf den Bildschirm zeichnet.
Du erstellst jedes mal ein neues Label in der "getTableCellRendererComponent". Die Methode heisst nicht createTableCellRendererComponent weil sie eben keinen neuen Component anlegen soll. Deine Klasse ist soll ein Renderer sein und keine Factory.
Du "extendest" ja sogar ein JLabel in deiner Klasse, verwendest aber keine einzige Funktion deiner Vaterklasse. So sollte ein Renderer aussehen:
Java:
public class TableHeader extends JLabel implements TableCellRenderer { 

    public TableHeader{
         super();
         this.setHorizontalAlignment(SwingConstants.CENTER);
         c.setEnabled(true);
         c.setBorder(UIManager.getBorder("TableHeader.cellBorder"));
         c.setOpaque(true);
         }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
        
        if(value instanceof String) {
            this.setText((String)value);
        }
        else{
        this.setText(null);
        }
        return this;
    }
 
}
 
Zuletzt bearbeitet:
Ein Beispiel vorher und nachher ist zum Beispiel.

Ohne eine extra Header für die Tabelle:

1867d1319003573t-customize-jtable-header-jtable.jpg


Und nach dem Einfügen eines neuen Header für die Tabelle.

JTable3.gif


Wobei
Java:
SwingUtilities.updateComponentTree(deineKomponente)
nicht funktioniert.
 
So,

Java:
public final class MyTable extends JTable {

  public MyTable() {

  init();

  }


private void init() {

  JTableHeader tableHeader = getTableHeader();
  tableHeader.setDefaultRenderer(new TableHeader()); 
  SwingUtilities.updateComponentTreeUI(this);

}
 
"SwingUtilities.updateComponentTreeUI(this);" hat dort nichts verloren, das musst du nur machen wenn du dein LnF während der Laufzeit ändern willst.
 
Ja, aber daran kann es nicht liegen. Es verändert sich nicht, on es da ist oder nicht.
Da ich da jetzt nicht weiter kommen und das alte L&F für den Header nicht hin bekommen und niemand eine Lösung hat, werde ich das erstmal so lassen.
 
Solange du kein KSKB postest kann ich dein Problem auch nicht nachvollziehen.
edit: Guckst du hier, 5 minuten Aufwand, alles wie es sein soll
Java:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;

public class TableHeaderKSKB extends JFrame
{
	
	private JPanel contentPane;
	private JTable table;
	
	/**
	 * Launch the application.
	 */
	public static void main(String[] args)
	{
		try
		{
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (Throwable e)
		{
			e.printStackTrace();
		}
		EventQueue.invokeLater(new Runnable()
			{
				public void run()
				{
					try
					{
						TableHeaderKSKB frame = new TableHeaderKSKB();
						frame.setVisible(true);
					} catch (Exception e)
					{
						e.printStackTrace();
					}
				}
			});
	}
	
	/**
	 * Create the frame.
	 */
	public TableHeaderKSKB()
	{
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 450, 300);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		contentPane.setLayout(new BorderLayout(0, 0));
		setContentPane(contentPane);
		
		JScrollPane scrollPane = new JScrollPane();
		contentPane.add(scrollPane, BorderLayout.CENTER);
		
		table = new JTable();
		table.setModel(new DefaultTableModel(new Object[][] { { "1", "3", "0" }, { "42", "12", "42" },
				{ "42", "3", null }, }, new String[] { "Sepp", "Frizt", "Franz" }));
		
		table.getTableHeader().setDefaultRenderer(new TableHeaderRenderer());
		
		scrollPane.setViewportView(table);
	}
	
	class TableHeaderRenderer extends JButton implements TableCellRenderer
	{
		
		public TableHeaderRenderer()
		{
			super();
		}
		
		@Override
		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
				boolean hasFocus, int row, int column)
		{
			
			if (value instanceof String)
			{
				this.setText((String) value);
			} else
			{
				this.setText(null);
			}
			return this;
		}
	}
}
 
Zuletzt bearbeitet:
Hi,

ich habe gerade dasselbe Problem. Und ich habe heute die Lösung gefunden.

Das Problem ist das der Default-Header-Renderer nicht abgeleitet werden kann. Diese Klasse hat Sun, warum auch immer, irgendwie intern versteckt. (Vielleicht weil es L&F abhängig ist?!)

Die Lösung ist vor der Installation des eigenen Renderer sich den installierten zu holen.
Java:
table.getTableHeader().getDefaultRenderer()
Dieses übergibt man dann an den eigenen Renderer(z.B. im Konstruktor). Im eigenen Renderer in der Method getTableCellRendererComponent(...) wird der Aufruf nun zuerst an den gespeicherten DefaultHeaderRenderer delegiert.
Anschließend kann man noch eigene Einstellungen... im Renderer machen.

Nicht vergessen das Rendererobjekt selbst zurück zu geben.

Abschließend noch ein paar Codefragmente:

Zuerst die Ermittlung des DefaultHeaderRenderer und setzen des eigenen Renderer(MultisortTableCellRenderer)
Java:
                final JTableHeader tableHeader = table.getTableHeader();
                final TableCellRenderer defaultRenderer = tableHeader.getDefaultRenderer();

                tableHeader.setDefaultRenderer(new MultisortTableHeaderCellRenderer(defaultRenderer));

Und hier die entscheidende Methode im Renderer:
Java:
    public Component getTableCellRendererComponent(final JTable table,
                                                   final Object value,
                                                   final boolean isSelected,
                                                   final boolean hasFocus,
                                                   final int row,
                                                   final int column) {
        Component result

        result = this.defaultRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        // z.B. eigene Aktionen
        setBorder(UIManager.getBorder("TableHeader.cellBorder"));

        return result;
    }
 

Zurück
Oben