可编辑的 JComboBox 在失去焦点时触发 ActionListener
Editable JComboBox firing ActionListener when losing focus
我正在编写扩展 JComboBox 的 class (UIPromptComboBox
)。组合框是可编辑的,对于 class 的一个应用程序,它是通过控制 ActionListener
实现的。
目前,编辑组合框时会触发 ActionListener
,这很好。然而,当我取消选择组合框时,这个 ActionListener
也会被触发,我无法区分这两个事件,我也不希望它在取消选择组合框时触发。
实施Class
private void addUIField() {
// Initialise and place combobox
this.myGuiTextField = new UIPromptComboBox();
myGuiTextField.setSize(COMBO_WIDTH, defaultHeight);
GuiUtils.positionControl(myPanel, myGuiTextField, myTop, PROMPT_X_LOC);
//Add action listener
myGuiTextField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
if (evt.getActionCommand().equals("comboBoxEdited")) {
newUIcreated((UIPromptComboBox) evt.getSource());
}
}
private void newUIcreated(UIPromptComboBox alteredGuiTextField) {
try {
UIPrompt uip = alteredGuiTextField.getUIPrompt(((PowerPointTextItem) myPPTRef).getValue());
if (!simInfo.isInPrompts(uip)) {
simInfo.addUIPrompt(uip);
alteredGuiTextField.addNewUIPrompt(uip);
}
} catch (MissingPowerpointItem ex) {
Exceptions.printStackTrace(ex);
}
}
});
}
Class 扩展 JComboBox
public class UIPromptComboBox extends JComboBox {
public UIPromptComboBox(UIPrompt[] items) {
super(items);
this.setEditable(true);
}
public UIPromptComboBox() {
this.setEditable(true);
this.setEnabled(false);
}
/**
* returns either the selected UI prompt or a new prompt using the example
* text
*
* @param exampleText only used if new prompt is created
* @return UI prompt selected
*/
public UIPrompt getUIPrompt(String exampleText) {
UIPrompt uIPrompt = null;
Object returnedItem = this.getSelectedItem();
if (returnedItem instanceof UIPrompt) {
uIPrompt = (UIPrompt) returnedItem;
} else if (returnedItem instanceof String) {
uIPrompt = new UIPrompt((String) returnedItem, exampleText);
}
return uIPrompt;
}
public void addNewUIPrompt(UIPrompt newPrompt) {
ActionListener[] actionListerners = this.getActionListeners();
this.removeActionListener(this);
this.addItem(newPrompt);
this.setSelectedItem(newPrompt);
for (ActionListener al : actionListerners) {
this.addActionListener(al);
}
}
/**
* Used for displaying a report value sentence
* i.e. a string that is not associated with UI Prompts
* @param newText report value sentence
*/
public void setText(String newText) {
this.removeAllItems();
this.addItem(newText);
this.setSelectedItem(newText);
}
/**
* For when the UI prompts can be added on construction
*
* @param currentUIs list of UI promts
*/
public void addItems(UIPrompt[] currentUIs) {
this.removeAllItems();
DefaultComboBoxModel boxModel = new DefaultComboBoxModel(currentUIs);
this.setModel(boxModel);
}
}
由于失去焦点导致多次触发导致创建多个对象并将其添加到列表中。我想我可能错误地实施了 ActionListener
。感谢您的帮助
如您所述,您只希望在用户按下回车键时触发事件。实现它的更好方法是使用键监听器而不是动作监听器。
myGuiTextField.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
newUIcreated((UIPromptComboBox) evt.getSource());
}
}
private void newUIcreated(UIPromptComboBox alteredGuiTextField) {
try {
UIPrompt uip = alteredGuiTextField.getUIPrompt(((PowerPointTextItem) myPPTRef).getValue());
if (!simInfo.isInPrompts(uip)) {
simInfo.addUIPrompt(uip);
alteredGuiTextField.addNewUIPrompt(uip);
}
} catch (MissingPowerpointItem ex) {
Exceptions.printStackTrace(ex);
}
}
});
这应该只会在用户按下 enter 时触发您的事件 newUIcreated
,而不会在其他时间触发。用这个替换你的动作监听器
终于找到问题了
UIPrompt
的显示包括添加一个有时包含换行符的字符串。
单击另一个字段的操作会触发 UIPrompt
的呈现,但是当它包含换行符时,它会再次触发 ActionListener
。这就是 comboBoxEdited 重复操作的原因。
我正在编写扩展 JComboBox 的 class (UIPromptComboBox
)。组合框是可编辑的,对于 class 的一个应用程序,它是通过控制 ActionListener
实现的。
目前,编辑组合框时会触发 ActionListener
,这很好。然而,当我取消选择组合框时,这个 ActionListener
也会被触发,我无法区分这两个事件,我也不希望它在取消选择组合框时触发。
实施Class
private void addUIField() {
// Initialise and place combobox
this.myGuiTextField = new UIPromptComboBox();
myGuiTextField.setSize(COMBO_WIDTH, defaultHeight);
GuiUtils.positionControl(myPanel, myGuiTextField, myTop, PROMPT_X_LOC);
//Add action listener
myGuiTextField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
if (evt.getActionCommand().equals("comboBoxEdited")) {
newUIcreated((UIPromptComboBox) evt.getSource());
}
}
private void newUIcreated(UIPromptComboBox alteredGuiTextField) {
try {
UIPrompt uip = alteredGuiTextField.getUIPrompt(((PowerPointTextItem) myPPTRef).getValue());
if (!simInfo.isInPrompts(uip)) {
simInfo.addUIPrompt(uip);
alteredGuiTextField.addNewUIPrompt(uip);
}
} catch (MissingPowerpointItem ex) {
Exceptions.printStackTrace(ex);
}
}
});
}
Class 扩展 JComboBox
public class UIPromptComboBox extends JComboBox {
public UIPromptComboBox(UIPrompt[] items) {
super(items);
this.setEditable(true);
}
public UIPromptComboBox() {
this.setEditable(true);
this.setEnabled(false);
}
/**
* returns either the selected UI prompt or a new prompt using the example
* text
*
* @param exampleText only used if new prompt is created
* @return UI prompt selected
*/
public UIPrompt getUIPrompt(String exampleText) {
UIPrompt uIPrompt = null;
Object returnedItem = this.getSelectedItem();
if (returnedItem instanceof UIPrompt) {
uIPrompt = (UIPrompt) returnedItem;
} else if (returnedItem instanceof String) {
uIPrompt = new UIPrompt((String) returnedItem, exampleText);
}
return uIPrompt;
}
public void addNewUIPrompt(UIPrompt newPrompt) {
ActionListener[] actionListerners = this.getActionListeners();
this.removeActionListener(this);
this.addItem(newPrompt);
this.setSelectedItem(newPrompt);
for (ActionListener al : actionListerners) {
this.addActionListener(al);
}
}
/**
* Used for displaying a report value sentence
* i.e. a string that is not associated with UI Prompts
* @param newText report value sentence
*/
public void setText(String newText) {
this.removeAllItems();
this.addItem(newText);
this.setSelectedItem(newText);
}
/**
* For when the UI prompts can be added on construction
*
* @param currentUIs list of UI promts
*/
public void addItems(UIPrompt[] currentUIs) {
this.removeAllItems();
DefaultComboBoxModel boxModel = new DefaultComboBoxModel(currentUIs);
this.setModel(boxModel);
}
}
由于失去焦点导致多次触发导致创建多个对象并将其添加到列表中。我想我可能错误地实施了 ActionListener
。感谢您的帮助
如您所述,您只希望在用户按下回车键时触发事件。实现它的更好方法是使用键监听器而不是动作监听器。
myGuiTextField.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
newUIcreated((UIPromptComboBox) evt.getSource());
}
}
private void newUIcreated(UIPromptComboBox alteredGuiTextField) {
try {
UIPrompt uip = alteredGuiTextField.getUIPrompt(((PowerPointTextItem) myPPTRef).getValue());
if (!simInfo.isInPrompts(uip)) {
simInfo.addUIPrompt(uip);
alteredGuiTextField.addNewUIPrompt(uip);
}
} catch (MissingPowerpointItem ex) {
Exceptions.printStackTrace(ex);
}
}
});
这应该只会在用户按下 enter 时触发您的事件 newUIcreated
,而不会在其他时间触发。用这个替换你的动作监听器
终于找到问题了
UIPrompt
的显示包括添加一个有时包含换行符的字符串。
单击另一个字段的操作会触发 UIPrompt
的呈现,但是当它包含换行符时,它会再次触发 ActionListener
。这就是 comboBoxEdited 重复操作的原因。