简体   繁体   English

循环中无法按JButton

[英]Can't press JButton while in loop

I'm trying to make a program that generates random numbers if the user presses a button. 我正在尝试制作一个可以在用户按下按钮时生成随机数的程序。 It should stop generating them, when the user presses the button the second time, and then it should print all the random numbers added together and the average random number, but I don't know how I should do this. 当用户第二次按下按钮时,它应该停止生成它们,然后应该打印所有加在一起的随机数和平均随机数,但是我不知道该怎么做。 When I'm in the loop i can't press the button. 当我处于循环中时,我无法按下按钮。 I'll be thankful for any help. 感谢您的帮助。 My Code: 我的代码:

package Test;

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

public class Average

{

static int sizeX = 200;
static int sizeY = 200;
static int maxNum = 100;
static int minNum = 1;
static boolean running = true;

static JButton b1 = new JButton("Click me");

static void JFrame()

{

     Toolkit tk = Toolkit.getDefaultToolkit();
      Dimension dim = tk.getScreenSize();

    JFrame f = new JFrame("Test");
    f.setSize(sizeX, sizeY);
    f.setVisible(true);
    f.setLocation((dim.width - sizeX) / 2, (dim.height - sizeY) / 2);
    f.setResizable(false);
    f.setAutoRequestFocus(true);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    f.add(b1);

}

static void ActionListener()

{

    b1.addActionListener(new ActionListener()//ActionListener

    {

      public void actionPerformed(ActionEvent e)//Execute when button is pressed

      {

            int numsGenerated = 0;
            double ave = 0;

            if (running == true)

            {

                while (true)

                {

                    double r = Math.random() * (maxNum - minNum) + minNum; //(maxNum - minNum) + minNum
                    numsGenerated++;

                      ave = ave + r;

                          System.out.println("Random: " + r);   

                          if (!running)

                          {

                              break;

                          }

                }

                running = false;

            }

            else

                {

                  System.out.println("");
                  System.out.println("All: " + ave);
                  System.out.println("Average: " + ave / numsGenerated);

                running = true;

                }

      }


    }); //ActionListenerEnd

}

  public static void main(String[] args)//Main

  {

  JFrame();
  ActionListener();

  }

}

As Ordous told in a comment, you should make a different thread for this work. 正如Ordous在评论中告诉的那样,您应该为此工作另辟thread径。 But you may need to synchronize on "running" variable to make sure it works always. 但是您可能需要同步“运行”变量,以确保其始终有效。

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

public class Average    
{
static Object lock=new Object();
static int sizeX = 200;
static int sizeY = 200;
static int maxNum = 100;
static int minNum = 1;
static boolean running = false;    
static JButton b1 = new JButton("Click me");    
static void JFrame()   
{   
     Toolkit tk = Toolkit.getDefaultToolkit();
      Dimension dim = tk.getScreenSize();  
    JFrame f = new JFrame("Test");
    f.setSize(sizeX, sizeY);
    f.setVisible(true);
    f.setLocation((dim.width - sizeX) / 2, (dim.height - sizeY) / 2);
    f.setResizable(false);
    f.setAutoRequestFocus(true);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    
    f.add(b1);

}

public class Thr extends Thread
{       
    @Override 
    public void run()
    {
          int numsGenerated = 0;
          double ave = 0;
          synchronized(lock)
          {
              running=!running;
          }
          if (running == true)
          {
              while (true)    
              {

                  double r = Math.random() * (maxNum - minNum) + minNum; //(maxNum - minNum) + minNum
                  numsGenerated++;    
                    ave = ave + r;    
                        System.out.println("Random: " + r);   
                        synchronized(lock)
                        {
                            if (!running)
                            {
                                break;
                            }
                        }
              }                  
              synchronized(lock)
              {
                  running = false;
              }
          }                 
              System.out.println("");
              System.out.println("All: " + ave);
              System.out.println("Average: " + ave / numsGenerated);
              running = true;       
    }   
}
static Thr thread=null;
static void ActionListener()    
{  
    b1.addActionListener(new ActionListener()//ActionListener  
    {    
      public void actionPerformed(ActionEvent e)//Execute when button is pressed

      {
          Average av=new Average();
          if(thread==null)
          {
               thread=av.new Thr(); // should add in an executor
               thread.start();
          }
          else
          {
              synchronized(lock)
              {
                  running=false;
              }
          }
      }


    }); //ActionListenerEnd    
}

  public static void main(String[] args)//Main    
  {    
      JFrame();
      ActionListener();    
  }    
}

To have a simple thread, "Thread" is inherited and run() methoud must be overridden to use it. 要拥有一个简单的线程,必须继承“线程”,并且必须重写run()方法才能使用它。 (you can use a "Runnable" instead of this too) (您也可以使用“ Runnable”代替)

public class Thr extends Thread
{       
    @Override 
    public void run()
    {

    }   
}

You start it like 你开始像

threadName.Start() 

or 要么

ExecutorObject.submit(threadName);

where executor object has a pool for threads to run efficiently and is created by executor service. executor对象具有一个使线程有效运行的池,并由executor服务创建。

Do not start threads with 不要以

  threadname.run()

directly. 直。

Also inter-thread communication is important. 线程间通信也很重要。 One thread leaves a message to somewhere, another thread reads. 一个线程将消息发送到某处,另一个线程读取。 If there is no synchronization, they can race for the variable's visibility and wrong output can happen. 如果没有同步,它们将争夺变量的可见性,并且可能发生错误的输出。

You can have an object to lock on. 您可以锁定一个对象。

  synchronized(lock)
  {

  }

so this block can be entered by only single thread until it exits from this block. 因此,该块只能由单线程进入,直到从该块退出。 You should leave a message for other threads, to say "its ready" and wake them up(iff they are waiting) with 您应该为其他线程留下一条消息,说“它准备好了”,并用它们唤醒(如果它们正在等待)

  synchronized(lock)
  {
           lock.notifyAll();
  }

then make the message-leaving thread (current thread) go on a waiting state so other threads can wake it up and let it exit the block. 然后使消息保留线程(当前线程)进入等待状态,以便其他线程将其唤醒并使其退出该块。

  synchronized(lock)
  {
           lock.notifyAll();
           lock.wait();
  }

but this alone is not enough because current thread accidentally exit the waiting state so you may force it to keep waiting: 但这还不够,因为当前线程意外退出了等待状态,因此您可以强制其继续等待:

  synchronized(lock)
  {
           lock.notifyAll();
           while(condition)
                lock.wait();
  }

if you make sure only a single thread can access a variable at a time, you can use it to communicate with other threads. 如果确保一次只有一个线程可以访问变量,则可以使用它与其他线程进行通信。

You can use some other ways to have barriers to synchronize all threads on a point so no threads can continue until all hit the same barrier. 您可以使用其他方法设置障碍来同步一个点上的所有线程,以便在所有线程都遇到同一障碍之前,所有线程都无法继续执行。 More communication can decrease overall performance. 更多的交流会降低整体性能。

Main program is a thread too, so it can wait, notify and synchronize. 主程序也是一个线程,因此它可以等待,通知和同步。

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

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