# JList in JTable einfügen



## Ned Nederlander (6. Dez 2010)

Hallo,
ich habe bislang einen CellEditor und einen CellRenderer:


```
class JListCellRenderer implements TableCellRenderer {
    public Component getTableCellRendererComponent(final JTable table,
            final Object value, final boolean isSelected,
            final boolean hasFocus, final int row, final int column) {
        return (JList) value;
    }
}
class JListCellEditor extends AbstractCellEditor implements TableCellEditor {
    private JList lst;
    public Object getCellEditorValue() {
        return lst;
    }
    public Component getTableCellEditorComponent(final JTable table,
            final Object value, final boolean isSelected,
            final int row, final int column) {
        lst = (JList) value;
        return lst;
    }
}
```

Sind diese zugewiesen, scheinen sie auch angenommen zu werden, sind allerdings leer.

```
table.getColumnModel().getColumn(2).setCellRenderer(new JListCellRenderer());
table.getColumnModel().getColumn(2).setCellEditor(new JListCellEditor());
```


Ich habe allerdings große Probleme, die Listen zu füllen. Irgendwie muss ja nun jeder Liste ein Vektor zugewiesen werden. Leider bekomm ich das nicht so ganz hin. ;(

Vielen Dank für eure Hilfe!


----------



## SlaterB (6. Dez 2010)

übe doch zunächst in der nomalen GUI eine JList darzustellen und dieser vorher Daten zuzuweisen,
oder meinst du dynamisch je nach Zeile/Spalte den Inhalt der JList zu ändern?

deswegen gibts ja getTableCellEditorComponent() die die JList zurückgibt, vorher kannst du beliebig neue Daten zuweisen,
aktuelle Index row/column sind als Parameter bekannt + die JTable und damit ihr Model


----------



## Michael... (6. Dez 2010)

Ich würde ausserdem nicht unbedingt JList- Instanzen ins TableModel stecken, damit hebelst Du das Renderer/Editorkonzept der JTable aus.


----------



## Ned Nederlander (6. Dez 2010)

ich soll vorab ne JList füllen, und die dann mit setValueAt dem entsprechenden feld hinzufügen?


@ Michael..., was du meinst ist mir leider nicht klar. ich möchte in jede zelle ne andere liste schreiben.


----------



## SlaterB (6. Dez 2010)

> ich soll vorab ne JList füllen, und die dann mit setValueAt dem entsprechenden feld hinzufügen?

ist das eine Frage oder eine Feststellung, beziehst du dich auf mein Posting?
ich sagte, dass du zunächst eine JList für sich testen solltest, ganz ohne JTable

----

ins Model gehören nur die Daten, die möglichen Elemente zur Auswahl + die aktuelle Selektion,
der Renderer befüllt eine JList mit diesen Daten und zeichnet diese für einen kurzen Augenblick,
für das nächste Feld wird dieselbe JList mit anderen Daten schon wieder gemalt usw.


----------



## Ned Nederlander (6. Dez 2010)

Ich dachte ich muss CellRenderer und CellEditor schreiben, um die Listen überhaupt erst in die Zellen zu setzen. Lieg ich da falsch?

Meinst du damit, es reicht eine Liste mit setValueAt in die Zellen der Tabelle zu schreiben?


----------



## SlaterB (6. Dez 2010)

> Lieg ich da falsch?

nein

> Meinst du damit, es reicht eine Liste mit setValueAt in die Zellen der Tabelle zu schreiben?

nein, genau das ist falsch, dein Code deutet das an, Object value ist der Wert aus den Zellen, den du auf JList castest,
das meinte Michael...

richtig ist
> private JList lst;
im Editor, im Renderer brauchst du das auch, wobei ich mich frage wie das aussehen soll,
möchstest du nicht lieber nur einen Wert anzeigen, dann im Renderer gar nix tun, 
und im Editor als Auswahl eine JComboBox statt JList? das ist viel bekannter, da gibts sicher massig Beispiele


----------



## Ned Nederlander (6. Dez 2010)

ich möchte einfach in einer spalte die möglichkeit haben, in einer zelle mehrere strings untereinander darzustellen. die liste erschien mir dafür die beste lösung, da ich bei einer TextArea probleme hatte, die zeilenhöhe entsprechend anzupassen.
bei ner combobox wird der inhalt ja leider erst angezeigt, wenn ich draufklicke.

wenn ihr andere möglichkeiten kennt, mehrere strings untereinander anzuzeigen, bin ich sehr dankbar.


----------



## SlaterB (6. Dez 2010)

tja, wenn es JList sein muss, dann mach mal, besteht aktuell eine Frage?

Internet-Suche brachte noch folgende Seite
Problem in having JList in JTable's cell

viel unterschiedlicher Code, aber irgendwo steht
> class ListCellRenderer extends JList implements TableCellRenderer
der Renderer selber ist eine JList, 
Code unter anderem

```
public Component getTableCellRendererComponent(JTable table,
        Object value, boolean isSelected, boolean hasFocus,
        int nRow, int nCol)
    {

        if (value instanceof int[])
            setSelectedIndices((int[])value);
```
da sieht man wie das value-Objekt aus dem Table-Model lediglich ein int[] mit den selektierten Spalten ist,
das ist weniger als eine ganze JList, aber auch schon schwierig, dafür braucht man ein eigenes komplexes TableModel,
nicht nur eine simples 2D-Feld von Strings, wie normalerweise für eine Table


----------



## Michael... (6. Dez 2010)

Ned Nederlander hat gesagt.:


> die liste erschien mir dafür die beste lösung, da ich bei einer TextArea probleme hatte, die zeilenhöhe entsprechend anzupassen.


Diese "Probleme" wirst Du bei einer JList ebenfalls haben - und wahrscheinlich noch mehr.
Willst Du einfach nur Text mehrzeilig in einer Tabellenzelle darstellen, dann nimm eine JTextArea als Renderer.
Beispiele und Lösungsansätze für das Problem mit der Zeilenhöhe solltest Du hier im Forum finden.


----------



## Ned Nederlander (7. Dez 2010)

ein problem wird da sein, dass ich die möglichkeit brauche, noch von hand weitere zeilen in einer zelle einzutragen. da muss sich die zeilenhöhe dann ja schliesslich auch ändern.


----------



## Michael... (7. Dez 2010)

Wenn man eine JTextArea als Renderer und Editor nimmt, würde ich es in etwa wie folgt machen. Die TextArea des Editors habe ich in eine JScrollPane gesteckt, so dass man bei der Eingabe neuer Zeilen navigieren kann. Die neue Zeilenhöhe der Tabelle wird erst nach dem Editieren gesetzt.


```
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;

import javax.swing.AbstractCellEditor;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
 
public class TextAreaRendererDemo extends JFrame {
    private JTable table;
 
    public TextAreaRendererDemo() {
    	DefaultTableModel model = new DefaultTableModel(null, new String[] {"Spalte 0", "Spalte 1"});
        table = new JTable(model) {
            public boolean editCellAt(int row, int column) {
                boolean b = super.editCellAt(row, column);
                if (column==1)
                    ((TextAreaEditor)table.getCellEditor(row, 1)).specialActivate();
                return b;
            }
        };
 
        this.getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
 
        table.getColumnModel().getColumn(1).setCellRenderer(new TextAreaRenderer());
        table.getColumnModel().getColumn(1).setCellEditor(new TextAreaEditor());
        
        table.getModel().addTableModelListener(new TableModelListener() {
            public void tableChanged(TableModelEvent evt) {
                for (int row = 0; row < table.getRowCount(); row++) {
                	table.setRowHeight(row, table.prepareRenderer(table.getCellRenderer(row, 1), row, 1).getPreferredSize().height);
                }
            }
        });
        
        model.addRow(new String[] {"test", "Zeile   1 von 4 \nZeile   2 von 4 \nZeile   3 von 4 \nZeile   4 von 4"});
        model.addRow(new String[] {"test", "Zeile   1 von 2 \nZeile   2 von 2"});
        model.addRow(new String[] {"test", "Zeile   1 von 1"});
    }
 
    class TextAreaEditor extends AbstractCellEditor implements TableCellEditor {
 
        private JTextArea area;
        private JScrollPane pane;
 
        public TextAreaEditor() {
            area = new JTextArea();
            area.setLineWrap(true);
            area.setWrapStyleWord(true);
            area.setBorder(BorderFactory.createLineBorder(Color.BLACK));
            pane = new JScrollPane(area);
        }
 
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            if (value != null)
                area.setText(value.toString());
            else
                area.setText("");
            return pane;
        }
 
        public Object getCellEditorValue() {
            return area.getText();
        }
        
        public void specialActivate() {
            area.requestFocusInWindow();
        }
    }
 
    class TextAreaRenderer extends DefaultTableCellRenderer {
        private JTextArea area;
 
        public TextAreaRenderer() {
            area = new JTextArea();
            area.setLineWrap(true);
            area.setWrapStyleWord(true);
        }
 
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            area.setText(value.toString());
            area.setForeground(c.getForeground());
            area.setBackground(c.getBackground());
            if (hasFocus)
                area.setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
            else
                area.setBorder(null);
            return area;
        }
    }
 
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                final JFrame frame = new TextAreaRendererDemo();
                frame.setBounds(0, 0, 500, 300);
                frame.setLocationRelativeTo(null);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
            }
        });
    }
}
```


----------



## Ned Nederlander (10. Dez 2010)

danke erstmal dafür. funktioniert super!

aber kannst du mir sagen, was zeile 24-31 genau machen? das ist mir nicht so richtig klar.


----------



## Michael... (10. Dez 2010)

Da die TextArea des Editors in einer JScrollPane eingebeten ist, habe ich dem Editor die Methode specialActivate() verpasst, damit beim Aktivieren des Editors über die Tastatur die Area sofort den Fokus bekommt.

Kannst ja mal den Unterschied ausprobieren: Navigiere mit den Cursortasten auf eine Zelle der zweiten Spalte und drücke einen Buchstaben. Die TextArea bekommt den Fokus und der Textcursor blinkt am Ende des Texts.
Kommentiere die Zeilen aus und probiere das selbe noch einmal.


----------

