使用Jcombox作為Jtable的單元格,想支援下拉和可手工輸入,發現手工輸入值後,焦點一離開,輸入的值丢失,變為下拉選擇的值,必須使用敲回車的方式或者tab鍵的方式才能儲存,覺得這樣很不友善,特意研究了源碼,發現重寫列的TableCellEditor的getCellEditorValue()即可。
但同時也存在另一個問題,發現焦點值被帶到下一行,是以又重寫了getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column),至此問題得到解決,以下是實作代碼:
import javax.swing.*;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import java.awt.*;
public class JTableJcomboxTest extends JFrame{
public JTableJcomboxTest(){
this.setSize(500,400);
this.setLayout(new BorderLayout());
JTable jtable = new JTable(20,2);
TableColumnModel columnModel = jtable.getColumnModel();
TableColumn column0 = columnModel.getColumn(0);
column0.setHeaderValue("名稱");
DefaultCellEditor editor = new DefaultCellEditor(new JTextField());
editor.setClickCountToStart(1);
column0.setCellEditor(editor);
TableColumn column1 = columnModel.getColumn(1);
column1.setHeaderValue("格式");
column1.setCellEditor(new MyComboxCellEditor());
JScrollPane scroll = new JScrollPane(jtable);
this.add(scroll);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main(String[] args) {
new JTableJcomboxTest();
}
private static class MyComboxCellEditor extends DefaultCellEditor{
private String[] items = new String[]{".java",".xml",".jpg"};
public MyComboxCellEditor() {
super(new JComboBox());
JComboBox combox = ((JComboBox) this.editorComponent);
combox.setModel(new DefaultComboBoxModel(items));
combox.setEditable(true);
}
@Override
public Object getCellEditorValue() {
//直接從編輯器中取值
ComboBoxEditor editor = ((JComboBox) this.editorComponent).getEditor();
return editor.getItem();
}
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
//解決焦點值被帶到下一行問題
JComboBox component = (JComboBox)super.getTableCellEditorComponent(table, value, isSelected, row, column);
component.removeActionListener(this.delegate);
component.removeAllItems();
int selectedIndex = -1;
for (int i = 0; i < items.length; i++) {
if(items.equals(value)){
selectedIndex = i;
}
component.addItem(items[i]);
}
if (selectedIndex == -1){
component.setSelectedItem(value);
}else {
component.setSelectedIndex(selectedIndex);
}
component.addActionListener(this.delegate);
return component;
}
}
}
運作結果:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TP310MnRVT4NGVOBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL4gzN1IjN0IjMwETMxkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)