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

时间:2015-11-13 00:43:55

标签: java swing

我有一些代码可以创建一个带有一些按钮的窗口,点击这些按钮会提示用户通过控制台输入(注意:我在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是一个基于按钮索引的类,通过控制台提示用户输入不同类型的输入

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

1 个答案:

答案 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?