Обновление компонентов swing правильно?
Я новичок в swing, любая помощь ценится.
в этом фрагменте кода я переворачиваю карту лицом вверх, если окажется, что они не совпадают, я хочу, чтобы они снова повернулись лицом вниз.
На данный момент, что происходит: 1. при нажатии на первую карту переворачивается 2. когда вторая карта нажата, происходит либо одна из двух вещей (a) если они одинаковы, они оба остаются на ногах, чего я и хочу (b) если они не одинаковы, я никогда не вижу 2-ю карту вообще, как она немедленно повторно отображает заднюю часть карты (и заднюю часть предыдущей карты также, как определено в моем методе).
Я думал, что включение таймера сна может держать 2-ю карту отображаемой в течение определенного периода времени, прежде чем вернуться, но это не так.
Я попытался использовать contentPane.revalidate (); & contentPane.перекрасить (); но это ничего не меняет.
Я поставил некоторые консольные выходы:
Console output:
Card: 0 set
Card: 6 set
Sleeping now
Card: 6 unset
Card: 0 unset
выше-результирующий вывод консоли при нажатии на две карты, которые не соответствуют
@Override
public void actionPerformed(ActionEvent e)
{
String buttonPressed = e.getActionCommand();
int pos = Integer.valueOf(buttonPressed);
action = Control.model.ReceiveCardsTurned(pos);
keypadArray[pos].setIcon(myIcons[pos]);
System.out.println("Card: "+pos+" set");
currentTime.setText("" + Control.model.time);
currentScore.setText("" + Control.model.score);
//contentPane.revalidate();
//contentPane.repaint();
if(Control.model.twoCardsTurned == false)
{
if (action == "unturn")
{
System.out.println("Sleeping now");
try
{
Thread.sleep(1000);
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
keypadArray[pos].setIcon(back);
keypadArray[Control.model.lastCard].setIcon(back);
System.out.println("Card: "+pos+" unset");
System.out.println("Card: "+Control.model.lastCard+" unset");
}
}
}
2 ответов
есть ряд важных понятий, которые вы, кажется, не хватает.
- Swing-это среда, управляемая событиями. Это означает, что нет средств (или, по крайней мере, очень мало), которые вы можете "ждать" ввода пользователя, как правило, вам просто нужно реагировать на их взаимодействие.
- Swing управляется одним потоком, известным как поток диспетчеризации событий (он же EDT). Ответственность за отправку/обработку событий, поступающих в приложение, лежит на этом потоке к соответствующим частям приложения, чтобы они могли принять меры.
- менеджер перекраски отправляет свои запросы на обновление в EDT.
любое действие, которое вы предпримете, чтобы остановить EDT от выполнения этой работы, сделает ваше приложение похожим на подвешенное.
вы никогда не должны выполнять какие-либо трудоемкие операции (например, ввод-вывод, циклы или Thread#sleep
например) на EDT, делая это, сделает ваше приложение "паузой", которая никогда хорошенький.
прочитайте параллелизм в Swing для получения дополнительной информации.
теперь у вас есть несколько вариантов. Вы могли бы использовать Thread
"ждать" в фоновом режиме и повернуть карты обратно или вы можете использовать SwingWorker
или javax.swing.Timer
.
другая проблема у вас, что вы никогда не должны обновлять какие-либо компоненты пользовательского интерфейса из любого Thread
кроме EDT. Это означает, если вы должны были использовать Thread
, вы стали бы ответственным за повторная синхронизация этого потока с EDT. Хотя это не сложно, это просто становится беспорядочным.
SwingWorker
и javax.swing.Timer
функциональные возможности, которые делают это намного проще.
нитки и SwingWorker
отлично подходит для выполнения фоновой обработки и просто будет излишним для этой проблемы. Вместо javax.swing.Timer
идеально подойдет здесь.
if (!Control.model.twoCardsTurned)
{
if ("unturn".equals(action))
{
new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
keypadArray[pos].setIcon(back);
keypadArray[Control.model.lastCard].setIcon(back);
System.out.println("Card: "+pos+" unset");
System.out.println("Card: "+Control.model.lastCard+" unset");
}
}).start();
}
}
это действительно простой пример. Возможно, вы захотите ввести некоторые элементы управления, которые не позволят пользователю щелкнуть что-нибудь, пока таймер не срабатывает, например;)
вы не можете спать в потоке отправки событий, потому что ваш GUI замерзнет. Вы должны использовать Качели Таймер. Для фоновых задач вам, вероятно, придется беспокоиться о будущем, взгляните на SwingWorker.