Swing JComboBox als CellEditor in JTable zeigt Elemente nicht sofort an

ElJarno

Bekanntes Mitglied
Hi Leute,
habe in einem CellEditor eine ComboBox erstellt und diese in einer JTable genutzt.
Java:
public class CellEditorComboBox extends DefaultCellEditor {

	private static final long serialVersionUID = -3831989493413833105L;
	private JComboBox comboBox;

	public JComboBox getComboBox() {
		return comboBox;
	}

	public CellEditorComboBox(Object[] items) {
		super(new JComboBox(items));
		this.comboBox = (JComboBox) this.getComponent();
	}
}
Nun lade ich die Daten in die Tabelle und wähle den richtigen Eintrag in der ComboBox aus.
Java:
private void setComboBoxElements() {
		for (int i = 0; i < this.tableBerechtigung.getColumnCount(); i++) {
			TableCellEditor cellEditor = this.tableBerechtigung
					.getColumnModel().getColumn(i).getCellEditor();
			if (cellEditor instanceof CellEditorComboBox) {
				CellEditorComboBox comboBox = (CellEditorComboBox) cellEditor;
				for (int j = 0; j < this.tableBerechtigung.getRowCount(); j++) {
					Object obj = this.tableBerechtigung.getModel().getValueAt(
							j, i);
					String comparekey = null;
					for (int q = 0; q < comboBox.getComboBox().getItemCount(); q++) {
						Object item = comboBox.getComboBox().getItemAt(q);
						if (item instanceof BaseDataBean) {
							comparekey = ((BaseDataBean) item).getKey();
						}

						if (comparekey != null
								&& comparekey.equals(obj.toString())) {
							// comboBox.getComboBox().setSelectedIndex(q);
							comboBox.getComboBox().getModel().setSelectedItem(
									comboBox.getComboBox().getModel()
											.getElementAt(q));
							// this.tableBerechtigung.getModel().setValueAt(obj,
							// j, i);
							break;
						}
					}
				}
			}
		}
	}
Trotzdem wird das richtige Element in der ComboBox nicht angezeigt, jedoch sobald man die ComboBox öffnet.
Irgend ne Idee?

Danke im Voraus

Gruß Jan
 
Bin mir nicht sicher, ob ich dich genau verstanden habe, aber die Values der Comboboxen in der Tabelle werden erst angezeigt, sobald du in die Zelle klickst (in den EditModus der Tabelle wechselst) ?

Falls dem so ist, scheint dir ein einfacher CellRenderer zu fehlen, da sich ein CellEditor nur um die Darstellung während des Editiervorgangs kümmert. Aber selbst dann müsste dir der Standardrenderer zumindest das Object.toString() anzeigen, sobald du ein Value ausgewählt hast. Kannst ja mal deine ComboBox außerhalb der Tabelle testen. Ansonsten wäre nen kleines funktionierendes Example ganz gut.
 
Also außerhalb der Tabelle funktioniert dieser auch. Einen Renderer Benutze ich auch:

Java:
public class CellRendererComboBox extends JComboBox implements TableCellRenderer {
    /**
	 * 
	 */
	private static final long serialVersionUID = -2344746674816268709L;

	public CellRendererComboBox(Object[] items) {
        super(items);
    }

    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
        if (isSelected) {
            setForeground(table.getSelectionForeground());
            super.setBackground(table.getSelectionBackground());
        } else {
            setForeground(table.getForeground());
            setBackground(table.getBackground());
        }

        // Select the current value
        setSelectedItem(value);
        return this;
    }
}

Java:
			this.tableBerechtigung.getColumnModel().getColumn(2).setCellEditor(
					new CellEditorComboBox(mitarbeiter));
			this.tableBerechtigung.getColumnModel().getColumn(2)
					.setCellRenderer(new CellRendererComboBox(mitarbeiter));
 
Das Problem ist noch viel schwerwiegender als gedacht. Da anscheinend der CellEditor für die ganze Spalte gilt wirkt sich setSelectedItem auch auf die ganze Spalte aus sprich der letzte Wert wird in alle Zeilen in den ComboBoxen übertragen. Zudem haben wir gerade rausgefunden, dass sobald die ComboBox einer Zeile von Hand geändert wird, sich alle anderen ComboBoxen ebenfalls ändern.
 
Ich habe dir mal ein kleines lauffähiges Example für einen Combobox CellEditor gemacht, da ich dein Example nicht auf die Schnelle implementieren konnte. Dies erweitert zwar lediglich Default-Komponenten aus Swing, aber vielleicht hilft es dir deinen Fehler zu finden, da hier die Combobox das gewünschte verhalten hat. Als Renderer hab ich einfach ein Label genommen, oder wolltest du explizit, dass man die Comboboxen in der Tabelle auch ohne Editmodus sieht?

Java:
/**
 * Combobox CellEditor Example
 * 
 * @author ymene
 */
public class MainFrameWithTable extends JPanel
{
  public MainFrameWithTable()
  {
    setLayout( new BorderLayout() );

    JScrollPane scrollPane = new JScrollPane();
    JTable table = new JTable( new FixedModel() );

    table.setFillsViewportHeight( true );

    table.setDefaultEditor( Integer.class, new ComboBoxCellEditor( new JComboBox( new Object[]{ 1, 2, 3 } ) ) );
    table.setDefaultRenderer( Integer.class, new IntegerCellRenderer() );

    scrollPane.setViewportView( table );
    add( scrollPane, BorderLayout.CENTER );
  }

  public static void main( String[] args )
  {
    JFrame frame = new JFrame( "Combobox Celleditor Example" );
    frame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE );
    frame.add( new MainFrameWithTable() );
    frame.pack();
    frame.setVisible( true );
  }
}


class FixedModel extends AbstractTableModel
{
  final Object rows[][]  = { { 1 }, { 2 }, { 3 } };
  final String headers[] = { "Digit" };

  public int getColumnCount()
  {
    return 1;
  }
  public String getColumnName( int column )
  {
    return headers[ column ];
  }
  public int getRowCount()
  {
    return 3;
  }
  public Object getValueAt( int row, int column )
  {
    return rows[ row ][ column ];
  }

  @Override
  public void setValueAt( Object aValue, int rowIndex, int columnIndex )
  {
    rows[ rowIndex ][ columnIndex ] = aValue;
  }

  @Override
  public boolean isCellEditable( int rowIndex, int columnIndex )
  {
    return true;
  }

  @Override
  public Class<?> getColumnClass( int columnIndex )
  {
    return Integer.class;
  }
}


class IntegerCellRenderer extends DefaultTableCellRenderer
{
  public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected,
                                                  boolean hasFocus, int row, int column )
  {
    JLabel label =
        (JLabel) super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column );

    if ( value != null )
      label.setText( value.toString() );

    return label;
  }
}


class ComboBoxCellEditor extends DefaultCellEditor
{
  public ComboBoxCellEditor( JComboBox component )
  {
    super( component );

    component.addActionListener( new ActionListener()
    {
      @Override
      public void actionPerformed( ActionEvent e )
      {
        stopCellEditing();
      }
    } );
  }

  @Override
  public Component getTableCellEditorComponent( JTable table, Object value, boolean isSelected, int row,
                                                int column )
  {
    JComboBox editor = (JComboBox) super.getTableCellEditorComponent( table, value, isSelected, row, column );

    editor.setSelectedItem( value );

    return editor;
  }

  @Override
  public Object getCellEditorValue()
  {
    return ((JComboBox) getComponent()).getSelectedItem();
  }
}

Vielleicht hilft es dir die Lösung selber zu finden.

Grüße,
ymene
 
Hi,
habs jetzt so gelöst, dass ich die Objekte die sich in der ComboBox verwende auch in das Tablemodel stecke. So erkennt die ComboBox das zu selektierende Item und wählt dieses automatisch aus.

Gruß Jan
 

Zurück
Oben