Swing JTable: Objekttyp einer Spalte nachträglich ändern

Nachtfalke

Aktives Mitglied
Hallo zusammen,

ich habe schon wieder ein Problem mit meinen Tabellen. Ich bin dabei, einen HTML-Renderer zu schreiben. Wenn dieser Renderer eine Tabelle abbilden soll, dann lege ich zunächst eine JTable ohne Zeilen und Spalten an. Die Zeilen und Spalten werden dann bei jedem <TR>- bzw. <TD>-Tag angehängt. Da ich zu diesem Zeitpunkt noch nicht weiß, welchen Objekttyp die neue Spalte haben soll, lege ich sie zunächst als String an. Dadurch wird der jeweiligen Zelle dann der Objekttyp JLabel zugewiesen. Bei bestimmten nachfolgenden Tags möchte ich aber nun in einer bestimmten Spalte den Objekttyp JProgressBar anzeigen. Wie kann ich den Objekttyp einer Spalte nachträglich ändern?
 
Dadurch wird der jeweiligen Zelle dann der Objekttyp JLabel zugewiesen. Bei bestimmten nachfolgenden Tags möchte ich aber nun in einer bestimmten Spalte den Objekttyp JProgressBar anzeigen. Wie kann ich den Objekttyp einer Spalte nachträglich ändern?

Hallo Nachtfalke,

wozu eigentlich den Spaltentyp ändern? Sollte er nicht immer JComponent.class sein?

Gruß,
André
 
Zuletzt bearbeitet:
wie bekomme ich dann eine JProgressBar statt eines JLabels in eine Zelle rein?

Wir brauchen einen CellRenderer, der den Wert der Zelle als RendererComponent zurückgibt und ein TableModel, das JComponent.class als ColumnClass zurückgibt, etwa so:
Java:
        table.setDefaultRenderer(JComponent.class, new MyRenderer());
        table.setModel(createModel());
...
    private MyTableModel createModel() {
        MyTableModel myModel = new MyTableModel();
        for (int column = 0; column < 4; column++) {
            myModel.addColumn("Title " + (column + 1));

        }
        for (int row = 0; row < 4; row++) {
            Object[] rowData = new Object[]{new JLabel(), new JLabel(),
                new JLabel(), new JLabel()};
            myModel.addRow(rowData);
        }
        return myModel;
    }
...
            JProgressBar progress = new JProgressBar(0, 100);
            int value = 30;
            progress.setValue(value);
            table.getModel().setValueAt(progress, row, column);
...
    class MyRenderer implements TableCellRenderer {

        private final Border BORDER_SELECTED = UIManager.getBorder(
                "Table.focusCellHighlightBorder");
        private final Border BORDER_EMPTY = BorderFactory.createEmptyBorder();

        @Override
        public Component getTableCellRendererComponent(final JTable table,
                final Object value, final boolean isSelected,
                final boolean hasFocus, final int row, final int column) {
            JComponent rendererComponent = (JComponent) value;
            if (rendererComponent != null) {
                if (isSelected) {
                    rendererComponent.setBorder(BORDER_SELECTED);
                } else {
                    rendererComponent.setBorder(BORDER_EMPTY);
                }
            }
            return rendererComponent;
        }
    }

    class MyTableModel extends DefaultTableModel {

        public MyTableModel() {
            super();
        }

        @Override
        public Class getColumnClass(final int columnIndex) {
            return JComponent.class;
        }
    }
}

Gruß,
André
 
Soweit so gut. Das funktioniert schonmal ganz gut. Leider funktioniert jetzt meine Einstellung der Vorder- und Hintergrundfarbe bei den JLabel-Zellen nicht mehr. Mein Renderer sieht so aus:
Java:
  private class myRendererClass extends DefaultTableCellRenderer {

    private class FormatDataClass {

      public String Background = "#ffffff", Foreground = "#000000";
      public Integer VertAlign = CENTER, HorAlign = LEFT;
      public Float FontSize = 14f;
    }
    private ArrayList<ArrayList<FormatDataClass>> format = new ArrayList<ArrayList<FormatDataClass>>();

    public FormatDataClass getFormat(Integer row, Integer col) {
      return format.get(row).get(col);
    }

    public void addFormatRow() {
      format.add(new ArrayList<FormatDataClass>());
    }

    public void addFormatCol(Integer row) {
      format.get(row).add(new FormatDataClass());
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
      JComponent c = (JComponent) value;
      System.out.println(c);
      if (c != null) {
        if (c.getClass() == JLabel.class) {
          ((JLabel) c).setBackground(new Color(Integer.decode(format.get(row).get(column).Background)));
          ((JLabel) c).setForeground(new Color(Integer.decode(format.get(row).get(column).Foreground)));
          ((JLabel) c).setHorizontalAlignment(format.get(row).get(column).HorAlign);
          ((JLabel) c).setVerticalAlignment(format.get(row).get(column).VertAlign);
          c.setFont(c.getFont().deriveFont(format.get(row).get(column).FontSize));
        }
      }
      return c;
    }
  }

Hat jemand eine Idee, warum die Methoden setBackground und setForeground nicht greifen? Die Methoden werden auf jeden Fall aufgerufen, aber die Zellen werden nicht entsprechend eingefärbt.
 
Wir sollten immer beachten, dass JLabels nicht standardmäßig undurchsichtig sind. Wenn wir beim JLabel den Hintergrund malen müssen, wird empfohlen, dass wir seine Opacity-Eigenschaft wiederum auf "true" setzen. Der folgende Codeausschnitt zeigt, wie dies zu tun ist:

Java:
     label.setOpaque (true);

Gruß,
André
 
Jepp. Hab ich inzwischen auch durch T&E herausgefunden. Dann noch ein paar kleinere Änderungen und jetzt flutscht es. Danke Dir für die Hilfe!
 

Zurück
Oben