1

つまり、JComboBox (またはその他の JComboBox ベースのセル エディター) エディターが関連付けられているセルにユーザーが入力するたびに、JTable がコンボ ボックスをドロップダウンするようにします。

4

2 に答える 2

1

基本的に、コンボに適切なリスナーをインストールし、ポップアップを明示的に開く必要があります。「適切」の最初の候補は、AncestorListener です。これは、ancestorAdded メソッドでポップアップを表示することを呼び出します。

残念ながら、それがすべてではないようです。テーブルの surrenderFocus プロパティが false の場合に機能します。true の場合、編集不可のコンボに対してのみ機能します。掘り下げた後、動作しない部分の理由は、ポップアップが祖先リスナーによって開かれた後の内部フォーカス転送 (コンボからテキストフィールドへ) であることが判明しました。その場合、エディターの editComponent が永続的にフォーカスを取得すると、ポップアップを開く 2 番目のリスナーが必要です。

複数のリスナーが日常的にお互いの足を踏み入れるので、両方を永続的にインストールするのではなく、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 に答える