0

Only the most recent comboBox values are showing up in both rows.

UPDATED MVCE Example:

package main;
import java.awt.Color;
import java.awt.Font;
import java.util.ArrayList;

import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
public class SwingDemo {
   public static void main(String[] argv) throws Exception {
      DefaultTableModel model = new DefaultTableModel(); 
      model.addColumn("Column 1");
      JTable table = new JTable(model);
      Font font = new Font("Verdana", Font.PLAIN, 12);
      table.setFont(font);
      table.setRowHeight(30);
      table.setBackground(Color.orange);
      table.setForeground(Color.white);
      JFrame frame = new JFrame();
      frame.setSize(600, 400);
      frame.add(new JScrollPane(table));
      frame.setVisible(true);
      
      
      //add 1st row
     
      model.addRow("".split(""));
      TableColumn testColumn1stRow = table.getColumnModel().getColumn(0);
      JComboBox<String> comboBoxTest = new JComboBox<String>();
      ArrayList<String> testArray = new ArrayList<String>();
      testArray.add("one");
      testArray.add("two");
      testArray.add("three");
      for (int i = 0; i < testArray.size(); i++) {
          comboBoxTest.addItem(testArray.get(i));
      }
      testColumn1stRow.setCellEditor(new DefaultCellEditor(comboBoxTest));
      
      //add 2nd row
      model.addRow("".split(""));
      TableColumn testColumn2ndRow = table.getColumnModel().getColumn(0);
      JComboBox<String> comboBoxTest2 = new JComboBox<String>();
      ArrayList<String> testArray2 = new ArrayList<String>();
      testArray2.add("four");
      testArray2.add("five");
      testArray2.add("six");
      for (int i = 0; i < testArray2.size(); i++) {
          comboBoxTest2.addItem(testArray2.get(i));
      }
      testColumn2ndRow.setCellEditor(new DefaultCellEditor(comboBoxTest2));
   }
}

Essentially every time I add a row it runs this code and then every row in column has the value of the most recently added combobox.

Any ideas on how to get around this?

  • Most probably the list returned by `wpsListObj.getWps_list()` is the same for all your rows. How are you creating this backing list? – Lino May 05 '21 at 17:10
  • @Lino this is not the case. Thank you for your input. I verified this. I think it has to do with the fact that the ```TableColumn wpsColumn``` affects every single row because its handling the column as a whole. I will view a dropdown JComboBox and it will have the correct values for that row but when I add a new row that is supposed to have different values all previous rows now have the values of the latest row I added when I look at their drop downs. –  May 05 '21 at 17:15
  • 2
    Please post a [mre] so we can copy the code into our IDE and run tests. Otherwise, we're all guessing. – Gilbert Le Blanc May 05 '21 at 17:20
  • @GilbertLeBlanc please see updated example –  May 05 '21 at 17:45
  • Generally you want a column to contain the same available options for each item in the table, but if you need to get this you'll need to create your own `CellEditor` and override the `getComponent()` in some way that you can build the `ComboBox` at that time, and not use the same one for all rows. Maybe using a custom listener to change the values when editing starts? – kendavidson May 05 '21 at 18:00
  • @kendavidson thank you for your input. In this instance I do not want the same available options because each new now the user will input information that will then change what options are available in the JComboBox. But I understand as far as best practices go there may be a better way to accomplish this (i.e. rotate the table so that each column is a 'record') –  May 05 '21 at 18:14
  • 1
    See: https://stackoverflow.com/questions/4211452/how-to-add-unique-jcomboboxes-to-a-column-in-a-jtable-java/4211552#4211552 for a basic working example. – camickr May 05 '21 at 19:33

1 Answers1

0

I think there is a misconception: a JTable doesn't have TableColumn objects for each row and each column - it has only TableColumn objects for columns.

That means that with

TableColumn testColumn1stRow = table.getColumnModel().getColumn(0);
// [...]
TableColumn testColumn2ndRow = table.getColumnModel().getColumn(0);

the variable testColumn1stRow and testColumn2ndRow reference the same TableColumn object (the one for the first column.)

If you need different JComboBoxes as cell editors for different rows, you must create your own JTable subclass and override public TableCellEditor getCellEditor(int row, int column):

public class MyTable extends JTable {
    // [...]

    @Override
    public TableCellEditor getCellEditor(int row, int column) {
        if (column == 0) {
            List<String> values = getValuesForRow(row);
            JComboBox<String> comboBoxTest = new JComboBox<String>();
            for (int i = 0; i < testArray.size(); i++) {
                comboBoxTest.addItem(testArray.get(i));
            }
            return new DefaultCellEditor(comboBoxTest);
        } else {
            return super.getCellEditor(row, column);
        }
    }

    // [...]
}

I've invented a method List<String> getValuesForRow(int row) to fill in the possible values for a row just to keep the example short.

Thomas Kläger
  • 17,754
  • 3
  • 23
  • 34
  • thank you for the response. Let me give this a try and I will accept the answer. Please give me a couple days as I am working on several projects at work right now. To be clear, your ```List values ``` would be the items for that rows comboBox? –  May 05 '21 at 18:13
  • 1
    @will yes, that would be the items for that rows comboBox (i.e. in your example "one", "two", "three" for the first row and "four", "five", "six" for the second row) – Thomas Kläger May 05 '21 at 18:29
  • last follow up question. In the ```else``` block of the if statement, to be clear (I am not much of a Java Swing user), the ```super.getCellEdititor(row,column)``` refers to the ```getCellEditor``` of the super class JTable (which is the normal JTable class)? –  May 05 '21 at 18:39
  • 1
    @will yes, that will call the `getCellEditor(int,int)` of the normal `JTable` class (so that the cell editors for other columns still work) – Thomas Kläger May 05 '21 at 18:41
  • @ Thomas Kläger sorry for the multiple follow ups (I know said the last one would be final one). So in the class where I instantiate the JTable I need to change it so it is the new ```MyJTable``` correct? Any other changes or weird functionality I should expect? –  May 05 '21 at 18:56
  • 1
    @will Yes, you would need to change the code that currently creates the `JTable` to create the new `MyTable`. You probably also need to add the constructor `public MyTable(TableModel tm) { super(tm); }`. Except for the `getCellEditor()` override there should be no unexpected behaviour. – Thomas Kläger May 05 '21 at 20:30
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/232016/discussion-between-will-and-thomas-klager). –  May 06 '21 at 00:53