Java,强制程序在循环时等待内部点击

时间:2015-01-18 17:32:05

标签: java swing wait mouselistener notify

好的,所以这不是很棒的代码,但基本上我需要强制一个更复杂的程序版本来等待while循环内部的单击。在下面制作waitForClick()方法的任何帮助都会很棒。所有应该发生的事情是用户点击JButton完成,程序将条件设置为false,并打印“完成”。

公共类GUI扩展了JFrame {

private static final long serialVersionUID = 3560258176733156660L;

public static void main(String[] args) {
    new GUI().setVisible(true);
}

private JButton finish;
private boolean condition;

public GUI() {
    condition = true;
    setLayout(null);
    setSize(250, 120);
    setTitle("Silly");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    finish = new JButton("Finish");
    finish.setBounds(50, 40, 100, 30);
    finish.addMouseListener(new MouseClickListener());
    add(finish);
    doThings();

}
public void doThings() {
    while (condition) {
        waitForClick();
    }
    System.out.println("Done");
}

public void waitForClick() {
    // Need this method to make program wait for the Listener below, don't know how to do this!

}

public class MouseClickListener implements MouseListener {

    public void mouseClicked(MouseEvent arg0) {

        if (arg0.getSource()==finish) {
            condition = false;
        }

    }

    @Override
    public void mouseEntered(MouseEvent arg0) {

    }

    @Override
    public void mouseExited(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mousePressed(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseReleased(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }

}

}

2 个答案:

答案 0 :(得分:3)

你想做的事情是不可能的。

Swing是单线程的。因此,如果您在该单个线程(EDT)上运行无限循环,您的UI将被阻止,甚至无法处理该鼠标单击。

那么你的可能性是什么:

  • 让你的循环在另一个线程上运行。然后可以使用Swing线程来处理鼠标事件,您可以从EDT调整标志。由于您从多个线程访问相同的标志,请考虑使用AtomicBoolean。如果您的循环实际上必须执行某些操作,这当然只是一个选项。如果您只是想等,请参阅下一个选项。
  • 不要试图等待,而是对事件做出反应。在您发布的代码中,您只需从构造函数中删除对doThings的调用即可。 MouseClickListener会调用doThings,您可以从doThings方法中删除等待循环。

除此之外,我强烈建议摆脱null布局并切换到真实LayoutManager

答案 1 :(得分:0)

查看http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.concurrent.CountDownLatch;

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

public class GUI extends JFrame implements ActionListener {

    private static final long serialVersionUID = 3560258176733156660L;

    public static void main(String[] args) {
        new GUI().setVisible(true);
    }

    private JButton finish;
    private boolean condition;

    private CountDownLatch startSignal = new CountDownLatch(1);
    private CountDownLatch doneSignal = new CountDownLatch(1);

    public Main() {
        condition = true;
        setLayout(null);
        setSize(250, 120);
        setTitle("Silly");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        finish = new JButton("Finish");
        finish.setBounds(50, 40, 100, 30);
        finish.addActionListener(this);
        add(finish);
        //doThings();//Probably better not to put this here.
        // If you need to do things on the button click simply place doThings() in the action listener.
    }

    public void doThings() {
        new Thread(new Worker(startSignal, doneSignal)).start();
        startSignal.countDown(); 
        waitForClick();
        System.out.println("Done");
        System.exit(0);
    }

    public void waitForClick() {
         try {
            doneSignal.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
        if (arg0.getSource()==finish) {
            condition = false;
            doThings();
        }
    }

         class Worker implements Runnable {
           private final CountDownLatch startSignal;
           private final CountDownLatch doneSignal;
           public Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
              this.startSignal = startSignal;
              this.doneSignal = doneSignal;
           }
           public void run() {
              try {
                startSignal.await();
                doWork();
                doneSignal.countDown();
              } catch (InterruptedException ex) {} // return;
           }

           void doWork() {
               // Do work here before finish
               for (int i = 0; i < 10000; i++) {
                   System.out.println("Running..." + Math.pow(i, i));
               }
           }
         }

}