我有一个有四列的JTable。在第二列中,我已经将JComboBox指定为我的列的单元格编辑器。我遇到的问题是我无法按照我想要的方式处理组合框。
我想要的是,在用户选择组合框中的项目后,程序应该向表格模型添加一个新行并将焦点移动到第一列中的这一新行。 < / p>
请协助,让我们专注于上面的大胆要求。如果可能,示例代码将做得最好。
第2课:
public class Model extends AbstractTableModel {
protected String[] colNames;
protected Vector data;
Model(String[] col) {
this.colNames = col;
this.data = new Vector();
}
@Override
public int getRowCount() {
return this.data.size();
}
@Override
public String getColumnName(int col) {
return this.colNames[col];
}
@Override
public int getColumnCount() {
return this.colNames.length;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Product record = (Product) data.get(rowIndex);
switch (columnIndex) {
case qi:
return record.getQuantity();
case di:
return record.getDecsription();
case ui:
return record.getPrice();
case ti:
return record.getTprice();
default:
return new Object();
}
}
@Override
public boolean isCellEditable(int row, int col) {
return col<=3;
}
@Override
public void setValueAt(Object value, int row, int column) {
Product record = (Product) data.get(row);
switch (column) {
case qi:
record.setQuantity((Integer) value);
break;
case di:
record.setDecsription((String) value);
break;
case ui:
record.setPrice((Double) value);
break;
case ti:
record.setTprice((Double) value);
break;
default:
System.out.println("invalid index");
}
fireTableCellUpdated(row, column);//this is for updating the cell
}
@Override
public Class getColumnClass(int column) {// returns a class representing the datatype of the data stored in that column
switch (column) {
case qi:
return Integer.class;
case di:
return String.class;
case ui:
case ti:
return Double.class;
default:
return Object.class;
}
}
public void addEmptyRow() {
data.add(new Product());
fireTableRowsInserted(
data.size() - 1,
data.size() - 1);
}
public boolean hasEmptyRow() {
if (data.isEmpty()) {
return false;
}
Product productRecord = (Product) data.get(data.size() - 1);
if (productRecord.getDecsription().trim().equals("")
&& productRecord.getPrice() == 0.0
&& productRecord.getQuantity() == 0
&& productRecord.getTprice() == 0) {
return true;
} else {
return false;
}}
第3课:
public final class Table {
JTable table;
JScrollPane sp;
static final String[] columNames = {"Quantity", "Description", "Unity Price", "Total Price", ""};
Model model = new Model(columNames);
String[] values = {"1", "2", "3"};
public Table() {
createTable();
}
public void createTable() {
JFrame f = new JFrame();
f.setSize(300, 300);
f.setVisible(true);
//information regarding the table here
table = new JTable();
table.setModel(model);
table.setSurrendersFocusOnKeystroke(true);
table.setPreferredScrollableViewportSize(new java.awt.Dimension(300, 300));
TableColumn col = table.getColumnModel().getColumn(1);
col.setCellEditor(new myComboBoxEditor(values));
col.setCellRenderer(new MyComboBoxRenderer(values));
sp = new javax.swing.JScrollPane(table);
//information on table model
model.addTableModelListener(new Table.InteractiveTableModelListener());
if (!model.hasEmptyRow()) {
model.addEmptyRow();
}
//
f.add(sp);
TableColumn hidden = table.getColumnModel().getColumn(Model.hi);
hidden.setMinWidth(2);
hidden.setPreferredWidth(2);
hidden.setMaxWidth(2);
hidden.setCellRenderer(new InteractiveRenderer(Model.hi));
}
public void highlightLastRow(int row) {
int lastrow = model.getRowCount();//return the number of rows - last row
if (row == lastrow - 1) {
table.setRowSelectionInterval(lastrow - 1, lastrow - 1);
} else {
table.setRowSelectionInterval(row + 1, row + 1);
}
table.setColumnSelectionInterval(0, 0);//setting it to the first column
}
class InteractiveRenderer extends DefaultTableCellRenderer {
protected int interactiveColumn;
public InteractiveRenderer(int interactiveColumn) {
this.interactiveColumn = interactiveColumn;
}
@Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (column == interactiveColumn && hasFocus) {
if ((Table.this.model.getRowCount() - 1) == row
&& !Table.this.model.hasEmptyRow()) {
Table.this.model.addEmptyRow();//this is where we append a new row
}
highlightLastRow(row);//making it get focus and highlighted
}
return c;//returning the component
}
}
public class InteractiveTableModelListener implements TableModelListener {
@Override
public void tableChanged(TableModelEvent evt) {
if (evt.getType() == TableModelEvent.UPDATE) {
int column = evt.getColumn();
int row = evt.getFirstRow();
System.out.println("row: " + row + " column: " + column);
table.setColumnSelectionInterval(column + 1, column + 1);
table.setRowSelectionInterval(row, row);
}
}
}
private class myComboBoxEditor extends DefaultCellEditor {
myComboBoxEditor(String[] items) {
super(new JComboBox(items));
}
}
private class MyComboBoxRenderer extends JComboBox implements TableCellRenderer {
public MyComboBoxRenderer(String[] items) {
super(items);
}
@Override
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());
}
setSelectedItem(value);
return this;
}
}
public static void main(String[] args) {
Table tab = new Table();
}}
答案 0 :(得分:0)
现在我看到问题所在。您的TableColumnRenderer应该将您想要的效果绑定到您创建的Combobox上的侦听器。
每当你拿到渲染器(或者更确切地说是你的InteractiveRenderer)时都不应该调用它
if (column == interactiveColumn && hasFocus) { if ((Table.this.model.getRowCount() - 1) == row && !Table.this.model.hasEmptyRow()) { Table.this.model.addEmptyRow();//this is where we append a new row } highlightLastRow(row);//making it get focus and highlighted }
这部分是罪魁祸首。你真正想要做的是将它移动到你的JComboBox上的一个监听器:
public MyComboBoxRenderer(String[] items) {
super(items);
// Java 8. Should be easy to convert to anonymous class
setActionListener(e -> {
Table.this.model.addEmptyRow();
this.highlightLastRow();
});
}