简体   繁体   English

ActionListener和for循环

[英]ActionListener and for loop

Dear friends of Stackoverflow, 尊敬的Stackoverflow朋友,

here what I'm trying to do: - I would like to have a simple frame with some buttons and a JTextArea - I would like to have a loop that, at every iteration, expects for me to click on a button: when I click on this button a bunch of stuff happens, but I can't get it right: - in one attempt I got the for loop to work but it would not stop, at every turn, it just took the first command and performed all 20 turns without stopping - in the current version I click the button and nothing happens - I have already researched SOF and a series of other sites, including the Oracle documents but (probably also due to my level of experience), I cannot find an explanation that is clear enough for me to understand 这是我想做的事情:-我想要一个带有一些按钮和JTextArea的简单框架-我希望有一个循环,每次迭代都希望我单击一个按钮:当我单击时在此按钮上发生了很多事情,但我做不到:-一次尝试,我使for循环起作用,但它并没有停止,在任何转弯处,它只接受了第一个命令并执行了全部20匝不停-在当前版本中,我单击按钮并没有任何反应-我已经研究了SOF和一系列其他站点,包括Oracle文档,但是(可能由于我的经验水平),我找不到以下解释:足够让我理解

here my code 这是我的代码

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");
                } 
            }
        }
    }

}

IMPORTANT: I'm well aware that the code above does not fit Java best practices: it's just a sample code to illustrate what I'm trying to do (the original code is a lot of lines in multiple classes) 重要提示:我很清楚上面的代码不适合Java最佳实践:它只是一个示例代码,用以说明我正在尝试做的事情(原始代码是多个类中的许多行)

I hope you can help me to understand where I'm doing wrong 希望您能帮助我了解我做错了什么

Many thanks in advance 提前谢谢了

Why is your code currently not working, and what was probably wrong with your previous attempt. 为什么您的代码当前无法正常工作,以及您先前的尝试可能出了什么问题。

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

This will add the same listener to each of your buttons. 这会将相同的侦听器添加到每个按钮。 When you click on either of these buttons, an ActionEvent is generated and send to the ActionListener . 单击这些按钮中的任何一个时,都会生成一个ActionEvent并将其发送到ActionListener

When you have a for loop in your ActionListener , the whole loop will be executed each time you click on any of these buttons. 当您在ActionListener有一个for循环时,每次您单击这些按钮中的任何一个都将执行整个循环。 It is the whole code block in the actionPerformed method that gets executed. 执行的是actionPerformed方法中的整个代码块。 This is probably what you discovered in your first attempt. 这可能是您第一次尝试时发现的。

Your current attempt has if (e.getSource()==action1) checks in the for loop. 您当前的尝试具有if (e.getSource()==action1)签入for循环。 However, the action1 in that statement is not the same as the button on which you clicked. 但是,该语句中的action1与您单击的按钮不同。 The action1 here refers to the field 这里的action1是指字段

private Object action1;

in your RoundLevelAction class. 在您的RoundLevelAction类中。 If you use a debugger, you will see that none of those if statements evaluate to true , which is why you have the impression that nothing happens. 如果使用调试器,您将不会看到所有if语句的评估结果都为true ,这就是为什么您会觉得什么都没有发生的印象。 In fact, the for loop is triggered but nothing is outputted because none of the if statements evaluated to true. 实际上, for循环已触发,但没有任何输出,因为所有if语句均未评估为true。

All the above can easily be discovered if you use a debugger, and place some breakpoints. 如果您使用调试器并放置一些断点,则可以轻松发现以上所有内容。

Now for the solution to your problem. 现在为您解决问题。 That is unclear to me. 我不清楚。

I would like to have a loop that, at every iteration, expects for me to click on a button 我希望有一个循环,每次迭代都希望我单击一个按钮

The problem with this requirement is that Swing is single threaded. 此要求的问题是Swing是单线程的。 This means that all Swing related operations should happen on a single thread (the E(vent)D(ispatch(T(hread)), and that same thread is used to handle the user input (eg mouse clicks) and to paint the UI. This also means that if you somehow block that single thread, your UI becomes unresponsible. 这意味着所有与Swing相关的操作都应在单个线程(E(vent)D(ispatch(T(hread)))上进行,并且该线程用于处理用户输入(例如,鼠标单击)并绘制UI这也意味着,如果您以某种方式阻止了该单个线程,则您的UI将变得不负责任。

So if you have a loop, you cannot simply block the EDT and wait for a button click. 因此,如果有循环,就不能简单地阻止EDT并等待按钮单击。 Since the EDT is blocked, it becomes impossible to click on the EDT. 由于EDT被阻止,因此无法单击EDT。

  • Either you loop on a separate thread, and wait in that thread until the user clicked on the button. 您可以在一个单独的线程上循环,然后在该线程中等待,直到用户单击该按钮。 The ActionListener associated to that button can then re-activate the thread 然后,与该按钮关联的ActionListener可以重新激活线程
  • You can show a dialog asking the user what to do next, and put those buttons in that dialog. 您可以显示一个对话框,询问用户下一步该怎么做,然后将这些按钮放在该对话框中。 Take a look at the JOptionPane#show... methods for this. 看一下JOptionPane#show...方法。

the excellent answer from Robin, although not a direct solution, made me think about the logic of the program, and ask myself: why do I have a for loop at all? Robin提供的出色答案(尽管不是直接解决方案)使我考虑了程序的逻辑,并问自己:为什么我完全有一个for循环? To count the turns backwards from 20 to 0? 要计算从20向0的倒数? Well..I can always count forward (duh!). 好吧..我总能向前计数(du!)。 So I got rid of the for loop altogether, put a counter++for each one of the else ifs, and encapsulated everything into an if counter<20. 因此,我完全摆脱了for循环,为else if的每一个放置一个counter ++,并将所有内容封装到if counter <20中。 Now every iteration is activated by the pressure of one of the buttons, the iterations go up and the game follows the logic. 现在,每次迭代都由一个按钮的压力激活,迭代上升,游戏遵循逻辑。 NOT THE BEST SOLUTION but "a" solution. 不是最佳解决方案,而是“一个”解决方案。 I hope this can be useful for another user 我希望这对其他用户有用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM