Using JTables with JComboBox Cell Editors in Frame-based Applications
This JTable has its own TableModel which sets the third and fourth columns only to be editable. Their editor is a JComboBox, as shown in the screenshot.
You can move the code of the MyTableModel class (keeping the same namespace) to a different .pas file and add its reference to the project file. We decided to keep the classes in the same file because they are fairly short.

Combo box cell editor in action
You can compare this code with the RemObjects C# version below it.
The code in table_app2.pas
namespace table_app2; interface uses java.util, java.awt.*, javax.swing.*; type TableDemo = public class(JFrame, TableModelListener) private lblChangedValue : JLabel; tblGrades : JTable; verticalBox : Box; sp : JScrollPane; model : MyTableModel; cbo : JComboBox; editor : TableCellEditor; public constructor; class method Main(args : array of String); method tableChanged(e : TableModelEvent); end; type MyTableModel = class(AbstractTableModel) private columnNames : array[0 .. 3] of String; data : array[0 .. 4] of array[0 .. 3] of Object; public constructor; method getColumnCount : Integer; method getRowCount : Integer; method getColumnName(col : Integer) : String; override; method getValueAt(row, col : Integer) : Object; method isCellEditable(row, col : Integer) : Boolean; override; method setValueAt(value : Object; row, col : Integer); override; end; implementation constructor TableDemo; begin model := new MyTableModel; verticalBox := Box.createVerticalBox; tblGrades := new JTable(model); tblGrades.getColumnModel.getColumn(0).setPreferredWidth(100); tblGrades.getColumnModel.getColumn(1).setPreferredWidth(100); tblGrades.getColumnModel.getColumn(2).setPreferredWidth(80); tblGrades.getColumnModel.getColumn(3).setPreferredWidth(80); tblGrades.getTableHeader.setReorderingAllowed(false); model.addTableModelListener(self); cbo := new JComboBox; cbo.addItem('Pass'); cbo.addItem('Fail'); cbo.addItem('Distinction'); cbo.setSelectedItem('Distinction'); cbo.setMaximumRowCount(4); editor := new DefaultCellEditor(cbo); tblGrades.getColumnModel.getColumn(2).setCellEditor(editor); tblGrades.getColumnModel.getColumn(3).setCellEditor(editor); sp := new JScrollPane(tblGrades); verticalBox.add(sp); lblChangedValue := new JLabel('Changed value: '); verticalBox.add(lblChangedValue); add(verticalBox); //Ensure app closes when you click the close button DefaultCloseOperation := JFrame.EXIT_ON_CLOSE; //Set window caption and size Title := 'Table Demo 2'; Size := new Dimension(400, 150); setVisible(true); end; class method TableDemo.Main(args : array of String); begin new TableDemo; end; method TableDemo.tableChanged(e : TableModelEvent); var strChanged : String; begin if e.getType = TableModelEvent.UPDATE then begin strChanged := 'Changed value: ' + tblGrades.getValueAt(e.getFirstRow, e.getColumn).toString; lblChangedValue.setText(strChanged); end; end; constructor MyTableModel; begin // inherited; columnNames := ['Forename', 'Surname', 'Theory', 'Practical']; data := [['Jo', 'Wood', 'Pass', 'Distinction'], ['John', 'Bode', 'Fail', 'Pass'], ['Kapil', 'Shah', 'Pass', 'Pass'], ['Kathy', 'Parr', 'Distinction', 'Pass'], ['Helen', 'Coe', 'Pass', 'Fail']]; end; method MyTableModel.getColumnCount : Integer; begin result := columnNames.length; end; method MyTableModel.getRowCount : Integer; begin result := data.length; end; method MyTableModel.getColumnName(col : Integer) : String; begin result := columnNames[col]; end; method MyTableModel.getValueAt(row, col : Integer) : Object; begin result := data[row][col]; end; method MyTableModel.isCellEditable(row, col : Integer) : Boolean; begin if col > 1 then result := true else result := false; end; method MyTableModel.setValueAt(value : Object; row, col : Integer); begin data[row][col] := value; fireTableCellUpdated(row, col); end; end.
RemObjects C# Version of Table Application
using java.awt; using javax.swing; using javax.swing.table; using javax.swing.@event; namespace table_app_cs { public class TableDemo : JFrame, TableModelListener { private JLabel lblChangedValue; private JTable tblGrades; private Box verticalBox; private JScrollPane sp; private MyTableModel model; private JComboBox cbo; private TableCellEditor editor; public TableDemo() { model = new MyTableModel(); verticalBox = Box.createVerticalBox(); tblGrades = new JTable(model); tblGrades.getColumnModel().getColumn(0).setPreferredWidth(100); tblGrades.getColumnModel().getColumn(1).setPreferredWidth(100); tblGrades.getColumnModel().getColumn(2).setPreferredWidth(80); tblGrades.getColumnModel().getColumn(3).setPreferredWidth(80); tblGrades.getTableHeader().setReorderingAllowed(false); model.addTableModelListener(this); cbo = new JComboBox(); cbo.addItem("Pass"); cbo.addItem("Fail"); cbo.addItem("Distinction"); cbo.setSelectedItem("Distinction"); cbo.setMaximumRowCount(4); editor = new DefaultCellEditor(cbo); tblGrades.getColumnModel().getColumn(2).setCellEditor(editor); tblGrades.getColumnModel().getColumn(3).setCellEditor(editor); sp = new JScrollPane(tblGrades); verticalBox.add(sp); lblChangedValue = new JLabel("Changed value: "); verticalBox.add(lblChangedValue); add(verticalBox); //Ensure app closes when you click the close button DefaultCloseOperation = JFrame.EXIT_ON_CLOSE; //Set window caption and size Title = "Table Demo"; Size = new Dimension(400, 150); setVisible(true); } public static void Main(string[] args) { new TableDemo(); } public void tableChanged(TableModelEvent e) { String strChanged; if (e.getType() == TableModelEvent.UPDATE) { strChanged = "Changed value: " + tblGrades.getValueAt(e.getFirstRow(), e.getColumn()).toString(); lblChangedValue.setText(strChanged); } } } public class MyTableModel: AbstractTableModel { private String[] columnNames = new String[3]; Object[][] data = new Object[4][]; public MyTableModel() { columnNames = {"Forename", "Surname", "Theory", "Practical"}; data = {{"Jo", "Wood", "Pass", "Distinction"}, {"John", "Bode", "Fail", "Pass"}, {"Kapil", "Shah", "Pass", "Pass"}, {"Kathy", "Parr", "Distinction", "Pass"}, {"Helen", "Coe", "Pass", "Fail"}}; } public Integer getColumnCount() { return columnNames.length; } public Integer getRowCount() { return data.length; } public override string getColumnName(Integer col) { return columnNames[col]; } public Object getValueAt(Integer row, Integer col) { return data[row][col]; } public override Boolean isCellEditable(Integer row, Integer col) { if (col > 1) return true; else return false; } public override void setValueAt( Object value, Integer row, Integer col) { data[row][col] = value; fireTableCellUpdated(row, col); } } }