Как сказал Джони, вы не должны спать в ActionListener, потому что каждый ActionListener вызывается в потоке диспетчеризации событий. Любая существенная задержка помешает Swing нарисовать любые ваши изменения (и также не даст Swing отреагировать на любой ввод пользователя).
Но вы можете выполнить вашу логику c и ваши сны в другой ветке. Единственное, что вам нужно помнить, это то, что вызовы методов Swing и конструкторов Swing могут не выполняться в другом потоке; при работе в другом потоке вы должны использовать EventQueue.invokeLater для выполнения этих вызовов методов.
При использовании нового потока это будет выглядеть примерно так:
Runnable sortTask = () -> {
try {
for (int i=0; i < arr.size()-1; ++i) {
for (int j=0; j < arr.size()-1-i; ++j) {
if (arr.get(j) > arr.get(j+1)) {
int tmp = arr.get(j);
arr.set(j, arr.get(j+1));
arr.set(j+1, tmp);
int index1 = j;
int index2 = j+1;
EventQueue.invokeLater(() -> {
animation a =
new animation(grid, arr.size(), index1, index2);
a.actionPerformed(null);
});
Thread.sleep(200);
}
}
}
} catch (InterruptedException e) {
System.out.println("Interrupted. Terminating sort.");
}
};
new Thread(sortTask, "Sort").start();
Как видите, вся операция сортировки была перемещена в Runnable, который затем передается в новый поток. Фактическая «анимация» выполняется в отдельном небольшом Runnable, который передается в EventQueue.invokeLater
, поскольку он содержит операции Swing и не разрешен для запуска в любом потоке, кроме потока диспетчеризации событий.
Возможно для выполнения sh вашего рода с использованием таймера, но для этого потребуется перестройка вашей логики c. Вы не сможете использовать петли for
. Я думаю, что создание Thread и сохранение использования for
будет более читабельным и с ним легче работать.
Некоторые другие примечания:
- Обратите внимание, что try / улов вокруг всего вида. Прерывания не случаются случайно; если кто-то прерывает ваш поток, это означает, что он просит вас прекратить то, что вы делаете и выйти как можно более чисто. Позволяя InterruptedException выходить из l oop, когда программа перемещает выполнение в блок
catch
, вы выполняете этот запрос. - Никогда не перехватывает
Exception
. Существует множество непроверенных исключений, которые существуют для выявления ошибок программиста, таких как NullPointerException, IllegalArgumentException и IndexOutOfBoundsException. Вы хотите, чтобы остановили вашу программу, потому что они содержат ошибки, которые вы, программист, должны исправить. Их подавление не заставит программу работать. - Как отметил Джордж З., строки - это объекты, и вы никогда не должны сравнивать объекты, используя
==
, так как это не проверяет, равны ли они по значению. , он сравнивает, являются ли они одним и тем же объектом, созданным в одном и том же месте в программе. Как сравнить строки в Java? объясняет это подробно. (Есть несколько особых случаев, когда безопасно сравнивать объекты с ==
, но строки определенно не входят в их число.) - Переменные
index1
и index2
необходимы, потому что могут быть только конечные переменные перешел во внутренние классы и лямбды. Они не должны быть объявлены с final
(хотя это разрешено); они просто должны быть эффективно окончательными, такими, какие они есть, потому что им присваивается значение только один раз.