5

JComboBoxドロップダウンリストで現在強調表示されている項目が変更されたときに反応できるようにしたいと思います。現在選択されているアイテムを取得する方法を探しているのではなく、強調表示されているアイテムを探していることに注意してください。ItemListenerマウスをこのポップアップの上に置くと、マウスの位置にあるアイテムが強調表示されますが、これは現在選択されているアイテムには影響しませんActionListener

JComboBox現在強調表示されている項目の追加情報 (ドキュメント) を表示する と結合されたツールチップで構成されるコンポーネントを作成しようとしています。

私の最初の試みとして、コンストラクターにいくつかのコードを追加しています (extended JComboBox):

import java.awt.BorderLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleState;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.SwingUtilities;
import javax.swing.plaf.basic.ComboPopup;

public class SomeFrame extends JFrame {

    private MyComboBox combo;

    public SomeFrame() {
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setSize(100,20);
        setLocationRelativeTo(null);
        setLayout(new BorderLayout());
        combo = new MyComboBox();        
        combo.setModel(new DefaultComboBoxModel(new String[]{"one", "two", "three", "four"}));
        add(combo);
        pack();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                SomeFrame frame = new SomeFrame();
                frame.setVisible(true);
            }
        });
    }    

    // this is the important part
    private static class MyComboBox extends JComboBox {

        public MyComboBox() {
            getAccessibleContext().addPropertyChangeListener(new PropertyChangeListener() {
                public void propertyChange(PropertyChangeEvent evt) {
                    if (AccessibleContext.ACCESSIBLE_STATE_PROPERTY.equals(evt.getPropertyName())
                            && AccessibleState.FOCUSED.equals(evt.getNewValue())
                            && getAccessibleContext().getAccessibleChild(0) instanceof ComboPopup) {
                        ComboPopup popup = (ComboPopup) getAccessibleContext().getAccessibleChild(0);
                        JList list = popup.getList();
                        System.out.println("--> " + String.valueOf(list.getSelectedValue()));
                    }
                }
            });
        }
    }

}

動作しているように見えますが、いくつかのいかがわしい経路と試行錯誤を経てこのコードにたどり着いたので、もっと良い方法が必要だと考えています。何か案は?上記のコードは本番環境でも安全ですか?

4

2 に答える 2

4

良い質問と良い解決策-updateUIで内部配線を更新しないaccessibleComboにバグがあるように見えることを除いて、つまり、LAFを切り替えるとき:

  • リストのアクセス可能な選択の変更は、comboPopup リストに登録された内部 ListSelectionListener によって起動されます
  • omboPopup は ui-delegate によって制御され、installUI で再作成されます
  • accessibleCombo は、その内部リストを新しく作成およびインストールされたリストに更新しません。

あなたがそれについてできることはあまりありません。したがって、リストの選択を直接聞くと、LAF 変更の再配線を完全に制御できます。

public static class XComboBox extends JComboBox {

    private ListSelectionListener listener;

    public XComboBox() {
        uninstall();
        install();
    }

    @Override
    public void updateUI() {
        uninstall();
        super.updateUI();
        install();
    }

    private void uninstall() {
        if (listener == null) return;
        getPopupList().removeListSelectionListener(listener);
        listener = null;
    }

    protected void install() {
        listener = new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                if (e.getValueIsAdjusting()) return;

                JList list = getPopupList();
                System.out.println("--> " + String.valueOf(list.getSelectedValue()));
            }
        };
        getPopupList().addListSelectionListener(listener);
    }

    private JList getPopupList() {
        ComboPopup popup = (ComboPopup) getUI().getAccessibleChild(this, 0);
        return popup.getList();

    }
}
于 2013-04-10T15:41:50.083 に答える
3

JComboBox と結合されたツールチップで構成されるコンポーネントを作成しようとしています

コンボ ボックスのカスタム レンダラーを作成します。次に、レンダラーで setToolTipText(...) メソッドを使用します。

JTable チュートリアルのセクションSpecifying Tool Tips For Cellsでは、テーブルに対してこれを行う方法を示しています。概念は、コンボ ボックス レンダラーと同じである必要があります。

于 2013-04-10T15:36:55.273 に答える