我正在使用 SwingX AutoCompleteDecorator
作为 JComboBox
。自动完成功能运行良好...
但是我很难确定最终用户选择的时刻;很少保留我的数据。
让我试着解释一下:组合框为每个选择触发一个“comboBoxChanged”-ActionEvent
。当用户键入字符并且组合框自动匹配和选择项目时,我必须忽略这些事件。如果用户点击返回键,则会生成“comboBoxEdited”-ActionEvent
,我可以保存所选值。很棒;-)
如果使用鼠标打开JComboBox-PopUp
并选择项目,则唯一触发的事件是“comboBoxChanged”-ActionEvent
(例如使用光标键自动匹配或选择项目时)。鼠标点击事件以某种方式被消耗!?这就是为什么我无法识别最终的鼠标选择。
我怎么能弄清楚呢?我侦听鼠标单击事件的失败尝试记录在此 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);
}
});
}
}
comboBox 没有最终选择的概念:所有选择都具有相等的语义权重,独立于其触发器(鼠标、键盘导航、编程方式、按核心中的第一个字母进行选择)并触发 actionEvent。对于普通和装饰的组合框,行为相同。
这正是您在大多数情况下所需要的:始终对选择做出反应,就好像它是最终的一样(无论这可能意味着什么)
如果你真的想把由mouseEvent触发的选择视为比其他任何东西触发的选择更最终(同样:为了获得良好的用户体验,通常不建议这样做,所以在评估时要非常非常小心),你可以检查actionEvent返回的修饰符:
if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0) {
// triggered by mouse
}
编辑
在评论中看到用例(感谢您提供它们!),意识到我的当心部分在错误的树上吠叫:-)
在这种情况下,鼠标与键盘手势确实具有不同的语义。
JComboBox不能最佳地支持该用例,触发太多。即使在内部也是如此,例如当使用组合框作为CellEditor时。这部分是由一个魔术客户端属性修复的:
public DefaultCellEditor(final JComboBox comboBox) {
editorComponent = comboBox;
comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
检测到该属性后,BasicComboBoxUI(实际上是 BasicComboPopup)键击导航仅在弹出窗口列表中选择,将列表选择的同步推迟到组合选择,直到通过 Enter 提交。这是部分的,因为前瞻(又名:按第一个字母键入和选择)仍然在组合中立即选择(从而提交)。
简短摘要:已经有一个 swing-internal 用例,它导致了一个已经可用的 swingx 内部解决方案,用于在表中自动完成编辑 - 一个名为 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);