[英]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。
ActionListener
associated to that button can then re-activate the thread ActionListener
可以重新激活线程 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.