如何仅在 JTable 的特定单元格中设置 JComboBox
How to set a JComboBox only in specific cell in a JTable
我只想在假定具有值列表的单元格内添加 JComboBox。下面是我的代码,但它在列的所有单元格中添加了组合框。让我知道我的代码中缺少什么以仅在选定的单元格上设置组合框。
public class PropertiesTableModel extends AbstractTableModel{
//this method is called to set the value of each cell
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Field field= (Field) fieldList.get(rowIndex);
if(columnIndex==0){
String dataType=field.getFieldDef().getDataType();
return PropertiesPanel.getPpIns().getDataTypeIcon(dataType);
}
if(columnIndex==1){
return field.getFieldDef().getfName();
}
else if (columnIndex==2){
if(field.getFieldDef().getListValue().size()>0){
return createValueListCombo(field.getFieldDef().getListValue());
}
return field.getDefaultValue();
}
else{
return null;
}
}
public JComboBox createValueListCombo(List<Value> valueList){
TableColumn valColumn = table.getColumnModel().getColumn(2);
JComboBox comboBox=new JComboBox();
for (Value val: valueList) {
comboBox.addItem(val.getDescription());
}
comboBox.setSelectedIndex(0);
valColumn.setCellEditor(new DefaultCellEditor(comboBox));
return comboBox;
}
}
其实很简单,两种方式都可以搞定
首先,您的模型应该通知 editor/table 当前单元格有值列表。
public class PropertiesTableModel extends AbstractTableModel {
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
// previous stuff
if (columnIndex == 2) {
// return the actually selected value,
// not the first value of the list!
// also the values changed by setValueAt() must be considered.
return null; // implement it!
}
}
public List<Object> getPossibleValues(int row, int column) {
// this method should return possible values to select.
// if cell has no possible values and should be editeb
// by a text field this methos should return null
if (column == 2) {
Field field= (Field) fieldList.get(rowIndex);
if (field.getFieldDef().getListValue().size() > 0) {
return field.getFieldDef().getListValue();
}
return null; // probably something else for non-list values
}
}
public void setValueAt(int row, int column) {
// you need to store the value chosen by the user
}
}
1) 覆盖 JTable
中的方法 public TableCellEditor getCellEditor(int row, int column)
public TableCellEditor getCellEditor(int row, int column) {
PropertiesTableModel model = (PropertiesTableModel) getModel();
List<Object> values = model.getPossibleValues(row, column);
if (values != null) {
return new DefaultCellEditor(new JComboBox(values.toArray()));
} else {
return super.getCellEditor(row, column);
}
}
2) 您可以创建自定义编辑器,根据当前编辑的单元格将所有调用委托给两个(或更多)编辑器之一。
public class CellEditorMulticaster implements TableCellEditor {
private DefaultTableCellEditor textEditor;
private DefaultTableCellEditor currentEditor;
public CellEditorMulticaster() {
firstEditor = new DefaultTableCellEditor(new JTextField());
}
Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected,
int row, int column) {
PropertiesTableModel model = (PropertiesTableModel) table.getModel();
List<Object> values = model.getPossibleValues(row, column);
if (values != null) {
currentEditor = new DefaultCellEditor(new JComboBox(values.toArray()));
} else {
currentEditor = textEditor;
}
return currentEditor.getTableCellEditorComponent(table, value,
isSelected, row, column);
}
public Object getCellEditorValue() {
return currentEditor.getCellEditorValue();
}
public boolean isCellEditable(EventObject anEvent) {
JTable table = (JTable) anEvent.getSource;
int row, col;
if (anEvent instanceof MouseEvent) {
MouseEvent evt = (MouseEvent) anEvent;
row = table.rowAtPoint(evt.getPoint());
col = table.columnAtPoint(evt.getPoint());
} else {
row = table.getSelectedRow();
col = table.getSelectedColumn();
}
PropertiesTableModel model = (PropertiesTableModel) table.getModel();
List<Object> values = model.getPossibleValues(row, column);
if (values != null) {
return true;
} else {
return textEditor.isCellEditable(anEvent);
}
}
public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
public boolean stopCellEditing() {
return currentEditor.stopCellEditing();
}
public void cancelCellEditing() {
currentEditor.cancelCellEditing();
}
// same pattern for another methods (delegate to currentEditor)
}
很抱歉,我无法添加评论,但我必须向 sergiy 的回答报告问题。
它用于第 1 步:1) 在 JTable
中覆盖方法 public TableCellEditor getCellEditor(int row, int column)
我发现每次单击组合框时,此代码都会创建一个新的组合框作为新的单元格编辑器。我的代码将在我点击 2-3 次后崩溃,因为索引超出了长度范围。
我对此一头雾水,希望能在这里得到答案。
我的代码是:
@Override
public TableCellEditor getCellEditor(int row, int column) {
TableModel model = (TableModel) getModel();
String[] values = model.getPossibleValues(row, column);
if (values != null) {
JComboBox<String> comboBox = new JComboBox<String>(values);
comboBox.addActionListener((e)->{
model.setValueAt(row, column, comboBox.getSelectedItem());
});
return new DefaultCellEditor(comboBox);
} else {
return super.getCellEditor(row, column);
}
}
我只想在假定具有值列表的单元格内添加 JComboBox。下面是我的代码,但它在列的所有单元格中添加了组合框。让我知道我的代码中缺少什么以仅在选定的单元格上设置组合框。
public class PropertiesTableModel extends AbstractTableModel{
//this method is called to set the value of each cell
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Field field= (Field) fieldList.get(rowIndex);
if(columnIndex==0){
String dataType=field.getFieldDef().getDataType();
return PropertiesPanel.getPpIns().getDataTypeIcon(dataType);
}
if(columnIndex==1){
return field.getFieldDef().getfName();
}
else if (columnIndex==2){
if(field.getFieldDef().getListValue().size()>0){
return createValueListCombo(field.getFieldDef().getListValue());
}
return field.getDefaultValue();
}
else{
return null;
}
}
public JComboBox createValueListCombo(List<Value> valueList){
TableColumn valColumn = table.getColumnModel().getColumn(2);
JComboBox comboBox=new JComboBox();
for (Value val: valueList) {
comboBox.addItem(val.getDescription());
}
comboBox.setSelectedIndex(0);
valColumn.setCellEditor(new DefaultCellEditor(comboBox));
return comboBox;
}
}
其实很简单,两种方式都可以搞定
首先,您的模型应该通知 editor/table 当前单元格有值列表。
public class PropertiesTableModel extends AbstractTableModel {
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
// previous stuff
if (columnIndex == 2) {
// return the actually selected value,
// not the first value of the list!
// also the values changed by setValueAt() must be considered.
return null; // implement it!
}
}
public List<Object> getPossibleValues(int row, int column) {
// this method should return possible values to select.
// if cell has no possible values and should be editeb
// by a text field this methos should return null
if (column == 2) {
Field field= (Field) fieldList.get(rowIndex);
if (field.getFieldDef().getListValue().size() > 0) {
return field.getFieldDef().getListValue();
}
return null; // probably something else for non-list values
}
}
public void setValueAt(int row, int column) {
// you need to store the value chosen by the user
}
}
1) 覆盖 JTable
public TableCellEditor getCellEditor(int row, int column)
public TableCellEditor getCellEditor(int row, int column) {
PropertiesTableModel model = (PropertiesTableModel) getModel();
List<Object> values = model.getPossibleValues(row, column);
if (values != null) {
return new DefaultCellEditor(new JComboBox(values.toArray()));
} else {
return super.getCellEditor(row, column);
}
}
2) 您可以创建自定义编辑器,根据当前编辑的单元格将所有调用委托给两个(或更多)编辑器之一。
public class CellEditorMulticaster implements TableCellEditor {
private DefaultTableCellEditor textEditor;
private DefaultTableCellEditor currentEditor;
public CellEditorMulticaster() {
firstEditor = new DefaultTableCellEditor(new JTextField());
}
Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected,
int row, int column) {
PropertiesTableModel model = (PropertiesTableModel) table.getModel();
List<Object> values = model.getPossibleValues(row, column);
if (values != null) {
currentEditor = new DefaultCellEditor(new JComboBox(values.toArray()));
} else {
currentEditor = textEditor;
}
return currentEditor.getTableCellEditorComponent(table, value,
isSelected, row, column);
}
public Object getCellEditorValue() {
return currentEditor.getCellEditorValue();
}
public boolean isCellEditable(EventObject anEvent) {
JTable table = (JTable) anEvent.getSource;
int row, col;
if (anEvent instanceof MouseEvent) {
MouseEvent evt = (MouseEvent) anEvent;
row = table.rowAtPoint(evt.getPoint());
col = table.columnAtPoint(evt.getPoint());
} else {
row = table.getSelectedRow();
col = table.getSelectedColumn();
}
PropertiesTableModel model = (PropertiesTableModel) table.getModel();
List<Object> values = model.getPossibleValues(row, column);
if (values != null) {
return true;
} else {
return textEditor.isCellEditable(anEvent);
}
}
public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
public boolean stopCellEditing() {
return currentEditor.stopCellEditing();
}
public void cancelCellEditing() {
currentEditor.cancelCellEditing();
}
// same pattern for another methods (delegate to currentEditor)
}
很抱歉,我无法添加评论,但我必须向 sergiy 的回答报告问题。
它用于第 1 步:1) 在 JTable
中覆盖方法 public TableCellEditor getCellEditor(int row, int column)我发现每次单击组合框时,此代码都会创建一个新的组合框作为新的单元格编辑器。我的代码将在我点击 2-3 次后崩溃,因为索引超出了长度范围。
我对此一头雾水,希望能在这里得到答案。
我的代码是:
@Override
public TableCellEditor getCellEditor(int row, int column) {
TableModel model = (TableModel) getModel();
String[] values = model.getPossibleValues(row, column);
if (values != null) {
JComboBox<String> comboBox = new JComboBox<String>(values);
comboBox.addActionListener((e)->{
model.setValueAt(row, column, comboBox.getSelectedItem());
});
return new DefaultCellEditor(comboBox);
} else {
return super.getCellEditor(row, column);
}
}