6

にSwingX AutoCompleteDecoratorを使用していJComboBoxます。オートコンプリート機能は美しく機能します...

しかし、最終的なユーザー選択の瞬間を特定するのに苦労しています。私のデータをめったに永続化しない。

ActionEvent説明してみましょう。コンボボックスは、選択ごとに「comboBoxChanged」を起動します。ユーザーが文字を入力し、コンボボックスが自動照合してアイテムを選択している間は、これらのイベントを無視する必要があります。ユーザーがリターンキーを押すと、「comboBoxEdited」ActionEventが生成され、選択した値を保存できます。素晴らしい ;-)

マウスを使用してJComboBox-PopUpを開き、アイテムを選択した場合、発生するイベントは「comboBoxChanged」-のみですActionEvent(自動照合またはカーソルキーでアイテムを選択する場合など)。マウスクリック-イベントはどういうわけか消費されます!?そのため、最終的なマウスの選択を識別できません。

どうすればこれを理解できますか?mouseClicked-Eventをリッスンしようとして失敗したのは、次のSSCCEに記載されています。

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import org.jdesktop.swingx.autocomplete.AutoCompleteDecorator;


public class SearchForThePopUpMouseClick extends JPanel
{
  private JComboBox<String> comboBox;

  public SearchForThePopUpMouseClick()
  {
    comboBox = new JComboBox<String>(new String[] { "Anna", "Marc", "Maria", "Marten", "Peter" });
    add(comboBox);
    add(new JTextField("textfield to click"));

    AutoCompleteDecorator.decorate(comboBox);


    comboBox.addActionListener(new ActionListener()
    {
      @Override
      public void actionPerformed(ActionEvent e)
      {
        System.out.println("Action Event with '" + e.getActionCommand() + " " + e.getID() + "'");
      };
    });


    ((Component) comboBox.getUI().getAccessibleChild(comboBox, 0)).addMouseListener(new MouseListener()
    {
      @Override
      public void mouseReleased(MouseEvent e)
      {
        System.out.println(e);
      }
      @Override
      public void mousePressed(MouseEvent e)
      {
        System.out.println(e);
      } 
      @Override
      public void mouseExited(MouseEvent e)
      {
        System.out.println(e);
      }
      @Override
      public void mouseEntered(MouseEvent e)
      {
        System.out.println(e);
      }
      @Override
      public void mouseClicked(MouseEvent e)
      {
        System.out.println(e);
      }
    });
  }


  public static void main(String[] args) throws Exception
  {
    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    SwingUtilities.invokeLater(new Runnable()
    {
      @Override
      public void run()
      {
        SearchForThePopUpMouseClick autoCompletePanel = new SearchForThePopUpMouseClick();
        JFrame frame = new JFrame("SwingX Autocomplete Example");
        frame.add(autoCompletePanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
      }
    });
  }

}
4

1 に答える 1

9

comboBoxには、最終的な選択の概念はありません。すべての選択は、トリガー(マウス、キーボードナビゲーション、プログラム、コアの最初の文字による選択)に関係なく、等しい意味上の重みを持ち、actionEventを起動します。プレーンおよび装飾されたコンボボックスでも同じ動作。

これは、ほとんどのコンテキストでまさに必要なことです。選択が最終的なものであるかのように常に反応します(それが意味するものは何でも)

あなたの場合、mouseEventによってトリガーされた選択を、他の何かによってトリガーされた選択よりも最終的なものと本当に見なしたい場合(これも、通常、優れたユーザーエクスペリエンスには推奨されないため、評価には非常に注意してください)、チェックできます。 actionEventによって返される修飾子:

if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0) {
    // triggered by mouse
}

編集

コメントでユースケース(提供してくれてありがとう!)を見て、私の注意が間違ったツリーに部分的に吠えていることに気づきました:-)

このコンテキストでは、マウスとキーボードのジェスチャは実際に異なるセマンティクスを持っています

  • キーボード:エディターでの入力とポップアップでのナビゲートは、最終的な選択を構築するプロセスを示し、特別なキー(Enter)はコミットを示します
  • マウス:ポップアップをクリックすると、選択とコミットの両方が行われます

JComboBoxはそのユースケースを最適にサポートしておらず、発火しすぎています。これは、コンボボックスをCellEditorとして使用する場合の内部的な問題です。これは、魔法のclientPropertyによって部分的に修正されています。

public DefaultCellEditor(final JComboBox comboBox) {
    editorComponent = comboBox;
    comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);

そのプロパティを検出すると、BasicComboBoxUI(実際にはBasicComboPopup)keyStrokesナビゲーションはポップアップのリストでのみ選択し、Enterを介してコミットされるまでlistSelectionのcomboSelectionへの同期を延期します。先読み(別名:最初の文字で入力して選択する)でも、コンボですぐに選択(およびコミット)するため、部分的です。

簡単な要約:swing-internalのユースケースがすでにあり、テーブルでのオートコンプリート編集のためのすでに利用可能なswingx-internalソリューション(ComboBoxCellEditorという名前のクラス)につながります。スタンドアロンでも使用できます:

AutoCompleteDecorator.decorate( withEditor );
ComboBoxCellEditor editor = new ComboBoxCellEditor(withEditor);
CellEditorListener listener = new CellEditorListener() {

    @Override
    public void editingStopped(ChangeEvent e) {
        // do commit stuff
    }

    @Override
    public void editingCanceled(ChangeEvent e) {
    }
};
editor.addCellEditorListener(listener);
contentPane.add(withEditor, BorderLayout.SOUTH);
于 2012-10-30T12:56:08.347 に答える