1

换句话说,我希望 JTable 在用户键入具有关联的 JComboBox(或任何其他基于 JComboBox 的单元格编辑器)编辑器的单元格时下拉组合框。

4

2 回答 2

1

基本上,您必须在组合上安装适当的侦听器并明确打开弹出窗口。“适当”的第一个候选者是 AncestorListener,它调用在其祖先添加方法中显示弹出窗口。

不幸的是,这似乎不是故事的全部:如果桌子的投降焦点属性为假,则有效。如果它是真的只适用于不可编辑的组合。经过一番挖掘,不工作部分的原因原来是在祖先监听器打开弹出窗口后的内部焦点转移(从组合到文本字段)。在这种情况下,我们需要第二个侦听器,它会在编辑器的 editingComponent 永久获得焦点后打开弹出窗口。

多个听众经常互相踩到对方的脚,所以最好不要永久安装两者,而是在每次调用 getEditorComp 时都这样做,并让他们在显示弹出窗口后自行卸载。下面是一个操作示例,请注意:它没有经过正式测试!

public static class DefaultCellEditorX extends DefaultCellEditor {
    private AncestorListener ancestorListener;
    private PropertyChangeListener focusPropertyListener;

    public DefaultCellEditorX(JComboBox comboBox) {
        super(comboBox);
    }

    /** 
     * Overridden to install an appriate listener which opens the
     * popup when actually starting an edit.
     * 
     * @inherited <p>
     */
    @Override
    public Component getTableCellEditorComponent(JTable table,
            Object value, boolean isSelected, int row, int column) {
        super.getTableCellEditorComponent(table, value, isSelected, row, column);
        installListener(table);
        return getComponent();
    }

    /**
     * Shows popup.
     */
    protected void showPopup() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                getComponent().setPopupVisible(true);
            }
        });
    }


    /**
     * Dynamically install self-uninstalling listener, depending on JComboBox
     * and JTable state. 
     * @param table
     */
    private void installListener(JTable table) {
        if (getComponent().isEditable() && table.getSurrendersFocusOnKeystroke()) {
            installKeyboardFocusListener();
        } else {
            installAncestorListener();
        }
    }

    private void installAncestorListener() {
        if (ancestorListener == null) {
            ancestorListener = new AncestorListener() {

                @Override
                public void ancestorAdded(AncestorEvent event) {
                    getComponent().removeAncestorListener(ancestorListener);
                    showPopup();
                }

                @Override
                public void ancestorRemoved(AncestorEvent event) {
                }

                @Override
                public void ancestorMoved(AncestorEvent event) {
                }

            };
        }
        getComponent().addAncestorListener(ancestorListener);
    }

    private void installKeyboardFocusListener() {
        if (focusPropertyListener == null) {
            focusPropertyListener = new PropertyChangeListener() {

                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    LOG.info("property: " + evt.getPropertyName());
                    if (focusManager().getPermanentFocusOwner() != 
                        getComponent().getEditor().getEditorComponent()) return;
                    focusManager()
                       .removePropertyChangeListener("permanentFocusOwner", focusPropertyListener);
                    showPopup();
                }

            };
        }
        focusManager().addPropertyChangeListener("permanentFocusOwner", focusPropertyListener);
    }

    /**
     * Convience for less typing.
     * @return
     */
    protected KeyboardFocusManager focusManager() {
        return KeyboardFocusManager.getCurrentKeyboardFocusManager();
    }

    /** 
     * Convenience for type cast.
     * @inherited <p>
     */
    @Override
    public JComboBox getComponent() {
        return (JComboBox) super.getComponent();
    }

}
于 2011-10-24T10:24:45.570 回答
0
    JTable table = new JTable(data, columns);
    table.putClientProperty("terminateEditOnFocusLost", true);
    JScrollPane scrollPane = new JScrollPane(table);
    final JXComboBox editorComboBox = new JXComboBox(array);
    editorComboBox.addAncestorListener(new AncestorListener() {
        public void ancestorAdded(AncestorEvent event) {
            //make sure combobox handles key events
            editorComboBox.requestFocusInWindow();
        }
        public void ancestorMoved(AncestorEvent event) {}
        public void ancestorRemoved(AncestorEvent event) {}
    });
    AutoCompleteDecorator.decorate(editorComboBox);
    TableColumn column = table.getColumnModel().getColumn(0);
    column.setCellEditor(new ComboBoxCellEditor(editorComboBox));
于 2015-02-02T11:37:21.457 回答