Java Eine JList (multiline cell) in einer JTable darstellen

CyborgBeta

Banned
Registriert
Jan. 2021
Beiträge
3.405
Hi ... habe ich hier etwas übersehen? Nach StackOverflow sollte das funktionieren ... Link: https://stackoverflow.com/a/32793088

Java:
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;

public class TableTest {
  static class MultiLineTableModel extends AbstractTableModel {
    private final List<String[]> data = new ArrayList<>();

    public void addRow(String[] row) {
      data.add(row);
      fireTableDataChanged();
    }

    public void clearRows() {
      data.clear();
      fireTableDataChanged();
    }

    @Override
    public int getRowCount() {
      return data.size();
    }

    @Override
    public int getColumnCount() {
      return 1;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
      return data.get(rowIndex);
    }

    @Override
    public String getColumnName(int column) {
      return "Messages";
    }
  }

  static class MultiLineTableCellRenderer extends JList<String> implements TableCellRenderer {
    @Override
    public Component getTableCellRendererComponent(
        JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
      if (value instanceof String[]) {
        setListData((String[]) value);
      }

      if (isSelected) {
        setBackground(UIManager.getColor("Table.selectionBackground"));
      } else {
        setBackground(UIManager.getColor("Table.background"));
      }

      return this;
    }
  }

  public static void main(String[] args) {
    MultiLineTableModel model = new MultiLineTableModel();
    JTable table = new JTable(model);
    table.setDefaultRenderer(String[].class, new MultiLineTableCellRenderer());
    JFrame frame = new JFrame();
    frame.add(new JScrollPane(table));
    frame.setSize(400, 400);
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    frame.setVisible(true);

    model.addRow(new String[] {"Index 1", "From 1", "Subject 1"});
    model.addRow(new String[] {"Index 2", "From 2", "Subject 2"});
  }
}

Anstatt multiline wird aber jeweils immer nur eine Zeile dargestellt:

1722604846047.png


Ich habe bestimmt in der main() was falsch gemacht. Danke.

BTW. Ich hasse unvollständige (oder falsche) SSCCEs ... und genau das scheint hier der Fall zu sein.
 
Was möchtest du denn erreichen? Ich hätte gedacht, dass du 3 Columns darstellen möchtest. Dann muss halt "getColumnCount()" 3 zurückgeben und "return data.get(rowIndex)" muss in "return data.get(rowIndex)[columnIndex];" geändert werden.
 
Ah, sorry. Ist ja auch aus dem Link ersichtlich.
Ergänzung ()

Dann fehlt wohl einfach der CellRenderer.
table.getColumnModel().getColumn(columnIndex).setCellRenderer(renderer);
 
So, es hat inzwischen geklappt:

1722606383854.png


Java:
  public static void main(String[] args) {
    MultiLineTableModel model = new MultiLineTableModel();
    JTable table = new JTable(model);
    table.getColumnModel().getColumn(0).setCellRenderer(new MultiLineTableCellRenderer());
    table.setRowHeight((table.getRowHeight() + 3) * 3);
    JFrame frame = new JFrame();
    frame.add(new JScrollPane(table));
    frame.setSize(400, 400);
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    frame.setVisible(true);

    model.addRow(new String[] {"Index 1", "From 1", "Subject 1"});
    model.addRow(new String[] {"Index 2", "From 2", "Subject 2"});
    model.addRow(new String[] {"Index 3", "From 3", "Subject 3"});
    model.addRow(new String[] {"Index 4", "From 4", "Subject 4"});
  }

Wie vermutet, war die StackOverflow-Antwort falsch, bzw. ließ unerwähnt, dass ein simples table.setDefaultRenderer(String[].class, new MultiLineTableCellRenderer()); nicht funktioniert.

Aber Hauptsache Upvotes ...
 
CyborgBeta schrieb:
Wie vermutet, war die StackOverflow-Antwort falsch, bzw. ließ unerwähnt, dass ein simples table.setDefaultRenderer(String[].class, new MultiLineTableCellRenderer()); nicht funktioniert.

Aber Hauptsache Upvotes ...
Hast du mal aufs Datum der Frage und der Antworten geschaut? Wenn z.B. vor 5 oder 10 Jahren jemand etwas mit Java 8 gemacht hast, muss das heute nicht mehr 1:1 mit Java 21 funktionieren.
 
  • Gefällt mir
Reaktionen: CyborgBeta
Aldjinn schrieb:
Hast du mal aufs Datum der Frage und der Antworten geschaut?
Ja gut, das stimmt auch wieder ... Aber die Vermutung liegt nahe, dass es auch schon "damals" nicht funktioniert hatte, aber keiner sich das so genau angeschaut hatte (oder wollte) ... 😕
Ergänzung ()

Und na ja, mittlerweile gibt es FX, und Swing/AWT sind etwas überholt :D (aber das ist Ansichtssache)
 
  • Gefällt mir
Reaktionen: Aldjinn
Aldjinn schrieb:
Wenn z.B. vor 5 oder 10 Jahren jemand etwas mit Java 8 gemacht hast, muss das heute nicht mehr 1:1 mit Java 21 funktionieren.
Und warum nicht?
Also deine Aussage mag grundsätzlich schon richtig sein, aber in dem Kontext hier ergibt sie einfach wenig Sinn.
 
  • Gefällt mir
Reaktionen: CyborgBeta
Beispiele: Alles was aus com.sun.* kommt und durchs Modulsystem seit Java 9 nicht mehr direkt nutzbar ist. Oder auch die alten javafx.* Packages. Oder sowas wie java.util.Vector.

Aber du hast Recht: Auf den oben genannten Code trifft das nicht zu.

Trotzdem müssen x Jahre alte Informationen die Technologie y betreffen, nicht mehr korrekt sein.
 
Was aber i.d.R. bereits zu Fehlern beim Compilieren führt und nicht zu "unerwartetem" Verhalten.
 
  • Gefällt mir
Reaktionen: CyborgBeta
CyborgBeta schrieb:
Aber Hauptsache Upvotes ...
die Variante funktioniert auch, aber du musst dann halt beim TableModel die Methode getColumnClass noch implementieren. Standardmaessig gibt die Object zurueck, das matched dann nicht mit deinem registrierten Renderer fuer String[] und es wird halt einfach ein JLabel mit der toString() Methode genutzt.
 
  • Gefällt mir
Reaktionen: tollertyp und CyborgBeta
abcddcba schrieb:
aber du musst dann halt beim TableModel die Methode getColumnClass noch implementieren,
🙏 Dickes Dankeschön an dich ... übersehen ;)
 
Zurück
Oben