我有一些代码可以创建一个带有一些按钮的窗口,点击这些按钮会提示用户通过控制台输入(注意:我在NetBeans中运行它)。现在我想继续使用控制台,所以我并不是在寻找一个解决方案,我在这里创建一个新的框架,要求通过GUI输入。
问题在于,当控制台从用户那里获取输入时,按钮仍然被启用,因此排队任何按下,当用户完成将内容输入控制台时,这些按钮会被执行。我想在控制台输入时禁用按钮。我认为按钮的.setEnabled(false)方法会这样做,我认为通常会这样做。看起来Java优先考虑用户输入,因此在用户完成对控制台的输入之前,按钮不会被禁用。一旦用户完成输入,按钮应该被重新启用,因此它们实际上从不被禁用。有问题的代码如下:
for(int i = 0; i < LABELS.length; i++) {
menu_a.add(new JButton(LABELS[i]));
menu_a.get(i).addActionListener((ActionEvent e) -> {
menu_a.stream().forEach((b) -> {b.setEnabled(false);});
menu_b.stream().forEach((b) -> {b.setEnabled(false);});
menu_c.stream().forEach((b) -> {b.setEnabled(false);});
if(!menu_a.get(menu_a.indexOf(e.getSource())).isEnabled()) {
MenuActions.MenuActions(menu_a.indexOf(e.getSource()) + 1, data);
menu_a.stream().forEach((b) -> {b.setEnabled(true);});
menu_b.stream().forEach((b) -> {b.setEnabled(true);});
menu_c.stream().forEach((b) -> {b.setEnabled(true);});
}
});
itemPanel.add(menu_a.get(i));
}
LABELS只是一个字符串数组,它们是按钮的标签。
MenuActions是一个基于按钮索引的类,通过控制台提示用户输入不同类型的输入
数据是一个对象,其中包含根据用户输入进行操作的数据,与我认为的问题无关。
答案 0 :(得分:-1)
所以@MadProgrammer是对的。我不得不查找并实现SwingWorker来获取执行我想要的代码。结果看起来像这样:
编辑:所以我并不知道我是通过修改原始语境之外的GUI元素来犯下危害人类罪。我改变了我的代码,现在它看起来像这样。
for(int i = 0; i < LABELS.length; i++) {
menu_a.add(new JButton(LABELS[i]));
menu_a.get(i).addActionListener((ActionEvent e) -> {
menu_a.stream().forEach((b) -> {b.setEnabled(false);});
menu_b.stream().forEach((b) -> {b.setEnabled(false);});
menu_c.stream().forEach((b) -> {b.setEnabled(false);});
new SwingWorker<Void, Void>() {
@Override
public Void doInBackground() {
menuActions(menu_a.indexOf(e.getSource()) + 1);
return null;
}
@Override
public void done() {
menu_a.stream().forEach((b) -> {b.setEnabled(true);});
menu_b.stream().forEach((b) -> {b.setEnabled(true);});
menu_c.stream().forEach((b) -> {b.setEnabled(true);});
}
}.execute();
});
panel_a.add(menu_a.get(i));
}
我创建了一个匿名的SwingWorker来照顾我想要的东西。 我最终不得不禁用doInBackground()方法中的按钮,否则它就不会禁用它们,而且我遇到了原来的问题。 (见下面的编辑)此外,menuActions现在引用了类中的私有方法,我想,因为它实际上只是从GUI中调用,我可能会将其移入。
编辑:所以我将禁用更改为在SwingWorker之外发生,现在它正常工作。我只是责备一个我没有保存我的更改,也许我正在重新编译旧代码。
我还发现了一些关于整个SwingWorker和EventDispatchThread业务的更多信息,我认为这些信息是相关的,并帮助我更好地理解事情。
工作流
SwingWorker的生命周期涉及三个线程:
当前线程:在此线程上调用execute()方法。它 安排SwingWorker在工作线程上执行并返回 立即。可以等待SwingWorker完成使用 得到方法。
工作线程:在此线程上调用doInBackground()方法。 这是所有背景活动应该发生的地方。通知 有关绑定属性更改的PropertyChangeListeners使用 firePropertyChange和getPropertyChangeSupport()方法。默认情况下 有两个可用的绑定属性:状态和进度。
事件调度线程:此处发生所有与Swing相关的活动 线。 SwingWorker调用process和done()方法和 通知此线程上的任何PropertyChangeListeners。
https://docs.oracle.com/javase/8/docs/api/javax/swing/SwingWorker.html
再次感谢@MadProgrammer指出我正确的方向,并立即让我知道我的原始代码是残暴的。
另外,我从这个答案中得到了代码:How do I use SwingWorker in Java?