@MicroKlizma

Как заставить кнопку в JavaFX ничего не делать?

Имеется кнопка, которая обрабатывает более-менее весомое по времени событие. В моем случае, она в JavaFX приложении при нажатии каждый раз отображает новую капчу. К кнопке привязан метод типа onAction из контроллера, в нем все это происходит. Я хочу, чтобы если я нажимал на кнопку один раз, а потом сразу же второй, то пока метод после первого нажатия еще не завершит свою работу, второй метод не вызывался. Допустим, в самом конце метода я вывожу в консоль слово "конец", и нужно, чтобы я мог нажимать на кнопку сколько угодно раз, пока не увижу это слово, и чтобы при этом ничего не происходило. Я пробовал по классике поставить флаг, типа в начале метода сделать
if (buttonIsPressed) return;
И после него buttonIsPressed = true а в конце всего buttonIsPressed = false
Но это не помогло. Я так понимаю, что эти методы имеют свойство как бы накапливаться, может добавляются в очередь, а потом исполняются один за другим, и вот сколько раз я нажму на кнопку, столько раз метод потом будет срабатывать. Если я нажимал на кнопку 10 раз за пару секунд, то по после того, как я закончил клацать, картинка капчи еще раз 5 поменялась, и продолжалось это длиться тоже где-то пару секунд, короче нежелательно, чтобы такое происходило. Я пишу приложение для себя, в целях изучения, то есть можно и так оставить, но душа хочет чтобы было идеально

Какие тут могут быть методы решения? Я подумал, что может быть нужно как-то создавать второй поток, и тогда все будет выполняться одновременно, параллельно, а не последовательно, а может просто поставить какую-то задержку, таймер на кнопку между нажатиями, но не знаю как это все реализовать. А может быть в JavaFX уже есть готовый какой-нибудь объект, метод, который мне поможет, и не нужно ничего придумывать? Не знаю
  • Вопрос задан
  • 465 просмотров
Решения вопроса 1
@MicroKlizma Автор вопроса
Благодаря комментам под вопросом и некоторому гуглению разобрался что к чему. Я решил проблему путем создания нового потока. Таким образом, поток будет работать параллельно с основным потоком. И в то время пока кнопка существует, параллельно и независимо другой поток может ей управлять. При нажатии на кнопку я вызываю метод onAction(), в котором создаю новый поток с точкой входа в виде метода, который все должен обрабатывать
public void onAction() throws InterruptedException {
        Thread thread = new Thread(this::someMethod);
        thread.start();
    }

Далее делаем в этом методе все, что хотели делать, но при этом, пока выполняется код, делаем кнопку неактивной: button.setDisable(true). Благодаря этому она меняет цвет и пропадает возможность по ней кликать (также вроде можно модифицировать ее стиль в этом состоянии в css файле: .button:disabled)
public void someMethod() {
        button.setDisable(true);
        //code
        button.setDisable(false);
    }

Это решение у меня работало нормально и так, как я хотел. Но оно вызывает исключение, хотя на него можно забить если обернуть в try catch, все равно будет работать:
Exception in thread "Thread-3" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3
Я считаю, что хороший программист должен с исключениями бороться :)
Как я понял, исключение выбрасывается тогда, когда меняется вид (UI), элементы (узлы) (node) приложения. Видимо, это можно делать только в FX applicaton thread. В моей программе я изменял текстовое поле и поле с изображением. И решение есть - делать все эти изменения с помощью Platform.runLater(). В него, так же как и при создании Thread, передается объект типа Runnable. Runnable - это функциональный интерфейс, поэтому вместо того, чтобы создавать целый класс, реализующий Runnable, для краткой записи воспользуемся лямбда-выражениями. В моем случае для моего приложения метод будет выглядеть примерно так:
public void someMethod() {
        button.setDisable(true);
        //some code
        Platform.runLater( () -> textField.setText(text) );
        //some code
        Platform.runLater( () -> imageView.setImage(image) );
        //some code
        button.setDisable(false);
    }

Интересно, что setDisable() по идее тоже нужно оборачивать в Platform.runLater(). Но я протестировал, программа срабатывала без исключений даже если не обернуть, хотя казалось бы, этот метод заставляет кнопку менять цвет и делает ее неактивной, некликабельной, меняет состояние кнопки (кстати узнать это состояние можно с помощью isDisabled()), но нет, все работает
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
Bell Integrator Ульяновск
До 400 000 ₽
Bell Integrator Ижевск
До 400 000 ₽
Bell Integrator Хабаровск
До 400 000 ₽
03 июл. 2024, в 20:14
20000 руб./за проект
03 июл. 2024, в 19:06
65000 руб./за проект
03 июл. 2024, в 18:59
30000 руб./за проект