Java, заставить программу ждать клика внутри цикла while

Итак, это не очень хороший код, но в основном мне нужно заставить более сложную версию этой программы ждать щелчка внутри цикла 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

    }

}

}


person David Aaron    schedule 18.01.2015    source источник
comment
Можете ли вы просто использовать кнопку или диалоговое окно?   -  person markspace    schedule 18.01.2015


Ответы (2)


То, что вы хотите сделать, невозможно.

Swing является однопоточным. Поэтому, если у вас есть бесконечный цикл, работающий в этом единственном потоке (EDT), ваш пользовательский интерфейс будет заблокирован и даже не сможет обработать этот щелчок мыши.

Итак, каковы ваши возможности:

  • Пусть ваш цикл работает в другом потоке. Затем поток Swing доступен для обработки события мыши, и вы можете настроить флаг из EDT. Поскольку вы затем получаете доступ к одному и тому же флагу из нескольких потоков, рассмотрите возможность использования AtomicBoolean. Это, конечно, только вариант, если ваш цикл действительно должен что-то делать. Если вы просто хотите подождать, см. следующий вариант.
  • Не пытайтесь ждать, а вместо этого реагируйте на событие. В опубликованном вами коде вы можете просто удалить вызов doThings из конструктора. Затем MouseClickListener вызовет doThings, и вы можете удалить цикл ожидания из метода doThings.

Кроме того, я настоятельно рекомендую избавиться от макета null и перейти на настоящий LayoutManager.

person Robin    schedule 18.01.2015

Посетите 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));
               }
           }
         }

}
person Joe    schedule 18.01.2015