Выход из бесконечного цикла с кнопкой - Java - PullRequest
0 голосов
/ 12 декабря 2011

Я все время искал решение для своей проблемы, но не могу найти ничего близкого. Вот моя проблема: я только начал изучать Swing на Java, и у меня есть приложение, которое щелкает случайным образом между минимальным и максимальным промежутком времени. Пользователь вводит минимальное и максимальное время и нажимает кнопку, которая запускает этот код:

    class CalcButtonListener implements ActionListener{

    @Override
    public void actionPerformed(ActionEvent arg0) {
        //get data from text fields and store as integers in milliseconds. 

        //create a robot and random number between min and max

        while(run == true){

            robot.mousePress(InputEvent.BUTTON1_MASK);
            robot.mouseRelease(InputEvent.BUTTON1_MASK);
            robot.delay(num.nextInt(max-min+1)+min);

            }
        }
    }
}

Я удалил некоторый код, потому что он не имел отношения к проблеме. Проблема в том, что у меня есть другая кнопка, чтобы установить для переменной run значение false, но после нажатия первой кнопки я не могу нажать вторую кнопку или кнопку выхода вверху.

Я уверен, что моя ошибка очень простая, но я ее не вижу. Спасибо за любые ответы, которые помогают мне лучше понять предмет.

Edit: изменен цикл while с "while (run = true)" на "while (run == true)".

Ответы [ 8 ]

4 голосов
/ 12 декабря 2011
 while(run == true){

"=" устанавливает значение true «==» сравнивает значение run с истинным

Также вы можете просто использовать

 while(run){
3 голосов
/ 12 декабря 2011

Взгляните на SwingWorker .И просто сделай while(run)

2 голосов
/ 12 декабря 2011

ОБНОВЛЕНИЕ Этот ответ обновляется, потому что @uckelman указал мне, что при условии run = true кнопка остановки никогда не прерывает цикл while, потому что его нужно изменить на run = false в пределахпетля.Затем я публикую простое и альтернативное решение этой логической проблемы, чтобы запланировать задачу повторно с помощью таймера.Для получения дополнительной информации, пожалуйста, проверьте этот SO вопрос.

О событиях для кнопок: если у вас есть две кнопки, одна для запуска цикла и одна для завершения цикла, просто попробуйте этот код:

    class CalcButtonListener implements ActionListener{

        private boolean run = true;
        private java.util.Timer timer = new java.util.Timer();
        private JButton start_loop, end_loop;

        //here the buttons initialization


        @Override
        public void actionPerformed(ActionEvent ae){
        if(ae.getSource()==start_loop){


            java.util.TimerTask task = new java.util.TimerTask() {
        @Override
        public void run() {
            doStuff();
        }
    };
    timer.schedule(task, java.util.Calendar.getInstance().getTime(), 500);//here the '500' means the time, 500 ms,
the task is repeatedly executed. 


        }

        if(ae.getSource()==end_loop){
            timer.cancel();//cancel the tasks scheduled
            System.out.println("Task cancelled!");
        }
    }

    private void doStuff(){
        robot.mousePress(InputEvent.BUTTON1_MASK);
            robot.mouseRelease(InputEvent.BUTTON1_MASK);
            robot.delay(num.nextInt(max-min+1)+min);


    }
    }

Теперь задача doStuff() планируется выполнять каждые 500 мс.

Другая информация о java.util.Timer и java.util.TimerTask .

О вашей проблеме:

Проблема в том, что у меня есть другая кнопка, чтобы установить для переменной переменную значение false, но после нажатия первой кнопки,Я не могу нажать вторую кнопку или кнопку выхода вверху по этому вопросу.

Как в предыдущем вопросе , так и на этой страниценаписано так:

Правило однопоточности Swing гласит, что компоненты Swing могут быть доступны только одному потоку.Это правило применяется как к получению, так и к установке, и один поток известен как поток события-диспетчеризации.

Правило однопоточности хорошо подходит для компонентов пользовательского интерфейса, поскольку они, как правило, используются в однозадачном режиме.в любом случае, с большинством действий, инициируемых пользователем.Кроме того, создавать безопасные для нитей компоненты сложно и утомительно: это хорошая вещь, которую нельзя делать, если этого можно избежать.Но при всех своих преимуществах правило однопотоковости имеет далеко идущие последствия.

Компоненты Swing, как правило, не будут соответствовать правилу однопоточности, если все их события не отправляются и не принимаются в потоке диспетчеризации событий.Например, события изменения свойств должны отправляться в потоке отправки событий, а события изменения модели - в потоке отправки событий.

Для основанных на модели компонентов, таких как JTable и JTree,Правило однопоточности подразумевает, что доступ к самой модели возможен только из потока событий.По этой причине методы модели должны выполняться быстро и никогда не должны блокироваться, иначе весь пользовательский интерфейс не будет отвечать на запросы.

Затем, если вы разрабатываете свой графический интерфейс с использованием одного потока, когда событие кнопки являетсяВыполнено, ваш графический интерфейс будет зависать, ожидая полного выполнения соответствующего события кнопки.В вашем случае, в бесконечном цикле, ваш GUI всегда будет зависать.

Я предлагаю использовать для вашего GUI SwingWorker или расширить Thread класс (затем разработка графического интерфейса в отдельном потоке) или реализация интерфейса Runnable .Другой альтернативой является использование Timer из пакета javax.swing.Timer.

Вы можете прочитать этот старый вопрос SO о SwingWorker: Как использовать SwingWorker в Java?

Учебник для SwingWorker: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html

Учебник по созданию темы: http://docs.oracle.com/javase/tutorial/essential/concurrency/

Вопрос по Timer: Обновление JPanelи атрибуты в графическом интерфейсе, с указанным пользователем таймером?

Учебное пособие по таймеру: http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html

2 голосов
/ 12 декабря 2011

Каждое событие будет обрабатываться одним потоком, называемым потоком диспетчеризации событий (EDT). Если внутри одного из событий имеется бесконечный вызов, EDT не сможет обработать следующее событие в очереди событий.

1 голос
/ 12 декабря 2011

Будьте осторожны с методом, подобным while(something), это может привести к зависанию программы, я рекомендую вам реализовать прослушивателей событий , чтобы избежать этой проблемы ...

1 голос
/ 12 декабря 2011

Вы должны прочитать о таймерах Swing:

http://java.sun.com/products/jfc/tsc/articles/timer/

То есть сделать вашу программу управляемой событиями.У приложений Swing уже есть цикл, работающий внутри них все время, называемый циклом обработки событий.Это не поможет, если вы начнете еще один.

0 голосов
/ 12 декабря 2011

while (run = true) почти наверняка не то, что вы хотите.Для этого при каждом выполнении условия цикла присваивается true run, что гарантирует, что цикл будет продолжаться всегда.

То, что вы, вероятно, пытались сказать, было while (run == true), которое проверяетrun верно.Лучше просто сказать while (run), что делает то же самое.

Если вы назначаете run из другого потока, обратите внимание, что вы должны сделать run volatile членомтвой класс.Если вы не присваиваете run где-то еще, то у вас есть логическая ошибка, поскольку нет способа вырваться из цикла.В этом случае вам нужно добавить тест внутри цикла и установить run в false, когда вы хотите, чтобы цикл остановился.(Или вы можете иметь while (true) и просто использовать break внутри цикла.)

0 голосов
/ 12 декабря 2011
run=true;
while(run == true){

...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...