【问题标题】:ActionListener and for loopActionListener 和 for 循环
【发布时间】:2015-04-09 13:49:55
【问题描述】:

Stackoverflow 的朋友们,

这是我想要做的: - 我想要一个带有一些按钮和 JTextArea 的简单框架 - 我希望有一个循环,在每次迭代时,我都希望我点击一个按钮:当我点击这个按钮时,会发生一堆事情,但我做错了: - 在一次尝试中,我让 for 循环工作,但它不会停止,每一次,它只接受第一个命令并执行所有 20 圈而没有停止 - 在当前版本中,我单击按钮,没有任何反应 - 我已经研究过 SOF 和一系列其他网站,包括 Oracle 文档,但是(可能也是由于我的经验水平),我找不到足够清晰的解释让我理解

这是我的代码

package game4_prova_forloop;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class GAME4_prova_forloop {

    public static void main(String[] args) {

        //create frame
        JFrame frame = new JFrame("Action Listener");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600, 600);
        frame.setLayout(new FlowLayout());
        frame.setVisible(true);   

        //crete text area panel, 
        JPanel pannelloTextArea = new JPanel(); 
        pannelloTextArea.setBackground(new Color(255, 204, 204));
        pannelloTextArea.setSize(400, 400);
        frame.add(pannelloTextArea); 
        GroupLayout pannelloTextAreaLayout = new GroupLayout(pannelloTextArea); 

        //create scrollPane
        JScrollPane scrollTextArea = new JScrollPane(); 

        //1) create JTextArea
        JTextArea mostraTesto = new JTextArea(20, 20); 
        mostraTesto.setLineWrap(true);  //make it wrap text 
            pannelloTextArea.add(scrollTextArea); //add it to scroll pane
            pannelloTextArea.revalidate();
                scrollTextArea.add(mostraTesto); //add the scroll pane to text area 
                scrollTextArea.setViewportView(mostraTesto); 

        //2) create buttons 
        JButton action1 = new JButton("1");
        frame.add(action1);
        JButton action2 = new JButton("2");
        frame.add(action2);
        JButton action3 = new JButton("3");
        frame.add(action3);

        //3) pass textArea in the RoundLevelAction class
        RoundLevelAction roundLevelActionObj = new RoundLevelAction(mostraTesto); //first issue: I get an error
        //4) add listener to JButtons
        action1.addActionListener(roundLevelActionObj);
        action2.addActionListener(roundLevelActionObj);
        action3.addActionListener(roundLevelActionObj);          
    }

//THIS IS WHERE I START TO HAVE PROBLEMS: WHEN I CLICK NOTHING HAPPENS, WHEN 
//I WOULD EXPECT THE FOR LOOP TO GO THROUGH ITERATIONS
    public class RoundLevelAction implements ActionListener {

        //add inside the listener the pieces of GUI that you'll use
        private JTextArea mostraTesto;
        private Object action1;
        private Object action2;
        private Object action3;
        private Object action4;
        private Object action5;
        private Object action6;

        //create class for JTextArea
        public RoundLevelAction(JTextArea mostraTesto){
            this.mostraTesto = mostraTesto; 
        }    

        //and, finally, what I really want to do: a loop that, at each turn, expects me to click on 
        //a button and does an action in response
        public void actionPerformed(ActionEvent e) {
            //now create the loop
            for (int round_counter=1; round_counter<21; round_counter++) {                                       
                if (e.getSource()==action1){                             
                    mostraTesto.append("\n description action 1 and a bunch of other stuff");
                }
                else if (e.getSource()== action2){ 
                    mostraTesto.append("\n description action 2 and a bunch of other stuff");
                } 
                else if (e.getSource()== action3){
                    mostraTesto.append("\n description action 3 and a bunch of other stuff");
                } 
            }
        }
    }

}

重要提示:我很清楚上面的代码不适合 Java 最佳实践:它只是一个示例代码来说明我正在尝试做的事情(原始代码是多个类中的很多行)

我希望你能帮助我了解我做错了什么

在此先感谢

【问题讨论】:

    标签: java swing loops for-loop actionlistener


    【解决方案1】:

    为什么您的代码当前无法运行,以及您之前的尝试可能有什么问题。

    action1.addActionListener(roundLevelActionObj);
    action2.addActionListener(roundLevelActionObj);
    action3.addActionListener(roundLevelActionObj);  
    

    这将为您的每个按钮添加相同的侦听器。当您单击其中任一按钮时,会生成一个ActionEvent 并发送到ActionListener

    当您的ActionListener 中有一个for 循环时,每次单击这些按钮时都会执行整个循环。被执行的是actionPerformed 方法中的整个代码块。这可能是您在第一次尝试时发现的。

    您当前的尝试在for 循环中进行了if (e.getSource()==action1) 检查。但是,该语句中的action1 与您单击的按钮不同。这里的action1指的是字段

    private Object action1;
    

    在您的 RoundLevelAction 班级中。如果您使用调试器,您将看到这些if 语句都不会评估为true,这就是为什么您会觉得什么都没有发生。 事实上,for 循环被触发,但没有任何输出,因为没有一个if 语句被评估为真。

    如果您使用调试器并放置一些断点,则可以轻松发现上述所有内容。

    现在解决您的问题。我不清楚。

    我希望有一个循环,在每次迭代中,我都期望它 点击按钮

    这个要求的问题是 Swing 是单线程的。这意味着所有与 Swing 相关的操作都应该发生在单个线程(E(vent)D(ispatch(T(hread)))上,并且同一线程用于处理用户输入(例如鼠标单击)和绘制 UI 。这也意味着,如果你以某种方式阻塞了那个单线程,你的 UI 就会变得不负责任。

    因此,如果您有循环,则不能简单地阻止 EDT 并等待按钮单击。由于 EDT 被屏蔽,因此无法点击 EDT。

    • 要么在单独的线程上循环,然后在该线程中等待,直到用户单击按钮。然后与该按钮关联的ActionListener 可以重新激活线程
    • 您可以显示一个对话框,询问用户下一步要做什么,然后将这些按钮放在该对话框中。看看JOptionPane#show... 方法。

    【讨论】:

    • 感谢 Robin 抽出宝贵时间将其解释得如此清楚。我在研究中找到了您的解决方案,但从未如此清楚地解释过。所以,如果我没看错,那就是完全改变逻辑并转向多线程。我最后一次寻求帮助是:你知道一个很好的教程来解释如何做到这一点吗?我问是因为当我过去发现这个建议并尝试按照教程进行操作时,我永远无法将它们应用到我的案例中
    • 并澄清我想要做什么...这是一个简单的游戏:迭代开始 -> 系统做了一些影响你生命值的事情 -> 你用你的按钮做了一些影响系统的事情生命值 -> 下一次迭代。进行 20 次迭代:如果你还活着,你就赢了
    • @Bugbearvirus 在这种情况下,我可能不会打扰单独的线程。每次按下按钮时,您都可以减少计数器。不需要循环。但我看到你自己已经想通了
    【解决方案2】:

    Robin 的出色回答,虽然不是直接的解决方案,但让我思考程序的逻辑,并问自己:为什么我有一个 for 循环?从 20 倒数到 0? 嗯..我总是可以向前数(呃!)。所以我完全摆脱了 for 循环,为每个 else if 放置一个 counter++,并将所有内容封装到 if counter

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-02
      • 1970-01-01
      • 1970-01-01
      • 2021-07-30
      • 2014-03-15
      • 1970-01-01
      • 2019-01-17
      相关资源
      最近更新 更多