当前位置: 首页 > 知识库问答 >
问题:

JComboBox作为JTable列编辑器

季博
2023-03-14
   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();
}}

共有1个答案

东郭腾
2023-03-14

现在我知道问题出在哪里了。您的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可编辑。 我怎么能对其他细胞有同样的行为。 再次您好,我已经更新了代码,以便使-如果我通过重写方法在单元格上单击一次,单元格可以编辑-如果我通过重写

  • 问题内容: 我正在为我的JTable列使用以下代码进行编辑/取消编辑,但是当用户重新排列列时,以下代码不起作用,代码的SSCCE如下: 问题答案: 请注意,模型索引和视图索引 不 相等。如前所述这里, 提供了从模型坐标转换为视图坐标- 和-的方法,以及从视图坐标转换为模型坐标- 和的方法。 本教程部分讨论了 对 行进行 排序和过滤 ,但是原理也适用于列。没有完整的示例,很难确定。

  • 我目前正在开发一个JComboBox组件,我希望在其中的组合框中有一个JTable用于下拉选择。我扩展了ListCellRenderer,并且在弹出窗口中有一个表。 我想用两种不同的方式来呈现。第一个作为所选行的绑定列的标签,当弹出窗口不可见时。第二种是在弹出窗口可见时用JScrollPane显示表。 不幸的是,当我这样做时,弹出窗口被缩小到列表的行高,这只为表的列留下了空间。 如果我只是使用滚动

  • } Jtable的定义如下: 按照@polet所说的提示,我更改了getValueAt方法,以返回PersianLetterIdPair: 但当我断开与TableCellRenderer的连接时,它会正确为:

  • < br >我有这段代码,其中我设计了一个< code >可编辑的JComboBox来侦听我的< code>keyPressed事件,并显示一条消息,说明键已被按下。但我不知道为什么这没用。作为初学者,我可能在逻辑上/概念上犯了错误。 因此,我想征求关于如何构建代码的建议,以使其工作。 密码