Java 如何防止通过控制台的输入优先于禁用按钮?

Java 如何防止通过控制台的输入优先于禁用按钮?,java,swing,Java,Swing,我有一些代码创建了一个窗口,其中包含一些按钮,当单击这些按钮时,会提示用户通过控制台进行输入(注意:我在NetBeans中运行这个程序)。现在我想继续使用控制台,所以我并不是在寻找一个解决方案,在这个解决方案中,我创建了一个新的框架,通过GUI请求输入 问题是,当console从用户那里获取输入时,所有按钮都仍然处于启用状态,因此,当用户完成向console输入内容时,所有按下的按钮都会排队等待,并且这些按钮会被执行。我想在控制台接收输入时禁用这些按钮。我认为按钮的.setEnabled(fal

我有一些代码创建了一个窗口,其中包含一些按钮,当单击这些按钮时,会提示用户通过控制台进行输入(注意:我在NetBeans中运行这个程序)。现在我想继续使用控制台,所以我并不是在寻找一个解决方案,在这个解决方案中,我创建了一个新的框架,通过GUI请求输入

问题是,当console从用户那里获取输入时,所有按钮都仍然处于启用状态,因此,当用户完成向console输入内容时,所有按下的按钮都会排队等待,并且这些按钮会被执行。我想在控制台接收输入时禁用这些按钮。我认为按钮的.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));
    }
for(int i=0;i{
菜单_a.stream().forEach((b)->{b.setEnabled(false);});
menu_b.stream().forEach((b)->{b.setEnabled(false);});
menu_c.stream().forEach((b)->{b.setEnabled(false);});
如果(!menu_a.get(menu_a.indexOf(e.getSource())).isEnabled()){
MenuActions.MenuActions(menua.indexOf(e.getSource())+1,数据);
菜单_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));
}
标签只是一个字符串数组,这些字符串是按钮的标签

MenuActions是一个基于按钮索引的类,它通过控制台提示用户输入不同类型的输入


数据是一个对象,它包含的数据是根据用户输入进行操作的,与我认为的问题无关。

所以@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));
    }
for(int i=0;i{
菜单_a.stream().forEach((b)->{b.setEnabled(false);});
menu_b.stream().forEach((b)->{b.setEnabled(false);});
menu_c.stream().forEach((b)->{b.setEnabled(false);});
新SwingWorker(){
@凌驾
公共无效doInBackground(){
菜单操作(菜单a.indexOf(e.getSource())+1);
返回null;
}
@凌驾
公众假期结束(){
菜单_a.stream().forEach((b)->{b.setEnabled(true);});
menu_b.stream().forEach((b)->{b.setEnabled(true);});
menu_c.stream().forEach((b)->{b.setEnabled(true);});
}
}.execute();
});
面板添加(菜单获取(i));
}
我创建了一个匿名的SwingWorker来满足我的需求。最后,我不得不禁用doInBackground()方法中的按钮,否则它将无法禁用它们,而我被原来的问题困住了。(请参见下面的编辑)此外,menuActions现在指的是类中的私有方法,我认为因为它实际上只从GUI调用,所以我最好将其移入

编辑:所以我将禁用更改为在SwingWorker之外进行,现在它工作正常。我会责怪我没有保存我的更改,也许我是在重新编译旧代码

我还发现了更多关于SwingWorker和EventDispatchThread业务的信息,我觉得这些信息是相关的,帮助我更好地理解事情

工作流程

SwingWorker的生命周期涉及三个线程:

当前线程:在此线程上调用execute()方法。信息技术 安排SwingWorker在工作线程上执行并返回 立即可以等待SwingWorker使用 获取方法

工作线程:在此线程上调用doInBackground()方法。 这是所有背景活动应该发生的地方。通知 PropertyChangeListeners关于绑定属性更改使用 firePropertyChange和getPropertyChangeSupport()方法。默认情况下 有两个绑定属性可用:状态和进度

事件分派线程:所有与Swing相关的活动都发生在此线程上 线SwingWorker调用process和done()方法和 通知此线程上的所有PropertyChangeListeners

再次感谢@MadProgrammer为我指明了正确的方向,并及时让我知道我的原始代码非常糟糕


另外,我从这个答案中导出了代码:

听起来更像是在阻止事件调度线程,有关更多详细信息,请参阅。一个可能的解决方案可能是使用从用户处读取输入no,no,no,oh出于理智之爱no。不要,永远不要从事件调度线程的上下文之外创建或修改任何UI组件,您的代码违反了Swing的单线程规则,这可能会导致无法描述的问题和奇怪。禁用
ActionListener
中的按钮,创建一个
SwingWorker
,并从
doInBackground
中的用户处获取输入,这将防止UI被阻止并变得无响应。制造