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;
}}
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();
}}
现在我知道问题出在哪里了。您的TableColumnRenderer应该将您想要的效果绑定到您创建的组合框上的侦听器。
当您获得呈现器(或者更确切地说是您的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();
});
}
我想要一个有4列的jtable。一列必须是组合框。其他列是字符串。 只要找到问题:在注释语句jcb.seteditable(true)时;,如果我在comboxcell上单击一次,它就会打开这个单元格。但我不知道为什么效果更好。此外,我希望combox可编辑。 我怎么能对其他细胞有同样的行为。 再次您好,我已经更新了代码,以便使-如果我通过重写方法在单元格上单击一次,单元格可以编辑-如果我通过重写
/////测试TBL
我目前正在开发一个JComboBox组件,我希望在其中的组合框中有一个JTable用于下拉选择。我扩展了ListCellRenderer,并且在弹出窗口中有一个表。 我想用两种不同的方式来呈现。第一个作为所选行的绑定列的标签,当弹出窗口不可见时。第二种是在弹出窗口可见时用JScrollPane显示表。 不幸的是,当我这样做时,弹出窗口被缩小到列表的行高,这只为表的列留下了空间。 如果我只是使用滚动
问题内容: 我正在为我的JTable列使用以下代码进行编辑/取消编辑,但是当用户重新排列列时,以下代码不起作用,代码的SSCCE如下: 问题答案: 请注意,模型索引和视图索引 不 相等。如前所述这里, 提供了从模型坐标转换为视图坐标- 和-的方法,以及从视图坐标转换为模型坐标- 和的方法。 本教程部分讨论了 对 行进行 排序和过滤 ,但是原理也适用于列。没有完整的示例,很难确定。
} Jtable的定义如下: 按照@polet所说的提示,我更改了getValueAt方法,以返回PersianLetterIdPair: 但当我断开与TableCellRenderer的连接时,它会正确为:
< br >我有这段代码,其中我设计了一个< code >可编辑的JComboBox来侦听我的< code>keyPressed事件,并显示一条消息,说明键已被按下。但我不知道为什么这没用。作为初学者,我可能在逻辑上/概念上犯了错误。 因此,我想征求关于如何构建代码的建议,以使其工作。 密码