Как создать задержку в Swing - PullRequest
10 голосов
/ 31 августа 2011

Я сделал игру в блэкджек и хочу, чтобы AI-игрок сделал паузу между взятием карт. Я попытался просто использовать Thread.sleep (x), но это останавливало его до тех пор, пока AI-игрок не забрал все свои карты. Я знаю, что Swing не является потокобезопасным, поэтому я посмотрел на таймеры, но я не мог понять, как я могу использовать один для этого. Вот мой текущий код:

while (JB.total < 21) {

          try {
            Thread.sleep(1000);
          } catch (InterruptedException ex) {
            System.out.println("Oh noes!");
          }

          switch (getJBTable(JB.total, JB.aces > 0)) {
            case 0:
              JB.hit();
              break;
            case 1:
              break done;
            case 2:
              JB.hit();
              JB.bet *= 2;
              break done;
          }
        }

Кстати, хит (); метод обновляет графический интерфейс.

Ответы [ 4 ]

7 голосов
/ 31 августа 2011

, поэтому я посмотрел на таймеры, но я не мог понять, как я мог бы использовать один для этого

Таймер является решением, так как, как вы говорите, вы обновляете графический интерфейс, который долженбыть сделано на EDT.

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

4 голосов
/ 31 августа 2011

Хорошо, следующий код показывает JFrame с JTextArea и JButton. При нажатии кнопок таймер повторно отправляет событие (со второй задержкой между ними) в actionListener, связанный с кнопкой, которая добавляет строку с текущим временем.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.Timer;


public class TimerTest extends JFrame implements ActionListener{

    private static final long serialVersionUID = 7416567620110237028L;
    JTextArea area;
    Timer timer;
    int count; // Counts the number of sendings done by the timer
    boolean running; // Indicates if the timer is started (true) or stopped (false)

    public TimerTest() {
        super("Test");
        setBounds(30,30,500,500);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(null);

        area = new JTextArea();
        area.setBounds(0, 0, 500, 400);
        add(area);

        JButton button = new JButton("Click Me!");
        button.addActionListener(this);
        button.setBounds(200, 400, 100, 40);
        add(button);

        // Initialization of the timer. 1 second delay and this class as ActionListener
        timer = new Timer(1000, this);
        timer.setRepeats(true); // Send events until someone stops it
        count = 0; // in the beginning, 0 events sended by timer
        running = false;
        System.out.println(timer.isRepeats());
        setVisible(true); // Shows the frame
    }

    public void actionPerformed(ActionEvent e) {
        if (! running) {
            timer.start();
            running = true;
        }
        // Writing the current time and increasing the cont times
        area.append(Calendar.getInstance().getTime().toString()+"\n");
        count++;
        if (count == 10) {
            timer.stop();
            count = 0;
            running = false;
        }
    }

    public static void main(String[] args) {
        // Executing the frame with its Timer
        new TimerTest();
    }
}

Ну, этот код является примером того, как использовать объекты javax.swig.Timer. В связи с частным случаем вопроса. Оператор if для остановки таймера должен измениться, и, очевидно, действия actionPerformed. Следующий фрагмент скелета решения actionPerformed:

public void actionPerformed(ActionEvent e) {
    if (e.getComponent() == myDealerComponent()) {
    // I do this if statement because the actionPerformed can treat more components
        if (! running) {
            timer.start();
            runnig = true;
        }
        // Hit a card if it must be hitted
        switch (getJBTable(JB.total, JB.aces > 0)) {
          case 0:
              JB.hit();
              break;
          case 1:
              break done;
          case 2:
              JB.hit();
              JB.bet *= 2;
              break done;
        }
        if (JB.total >= 21) { // In this case we don't need count the number of times, only check the JB.total 21 reached
            timer.stop()
            running = false;
        }

    }
}

ИМХО это решает проблему, теперь @ user920769 должен подумать, куда поместить actionListener и условия запуска / остановки ...

@ kleopatra: Спасибо, что показали мне существование этого класса таймера, я ничего о нем не знаю, и это удивительно, я могу сделать много задач с заданиями в свинг-приложении:)

4 голосов
/ 31 августа 2011

Ну, краткое объяснение о таймерах.

Прежде всего, вам нужна переменная java.util.Timer в вашем классе и другой класс в вашем проекте, который происходит от java.util.TimerTask (назовем его Tasker).

инициализация переменной Timer так проста:

Timer timer = new Timer();

Теперь класс Tasker:

public class Tasker extends TimerTask {
    @Override
    public void run() {
        actionToDo(); // For example take cards 
    }

    // More functions if they are needed
}

Наконец, установка таймера с соответствующим Tasker:

long delay = 0L;
long period = pauseTime;
timer.schedule(new Tasker(),delay,period);

Функция расписания показывает следующее: Fisrt param: Действие для выполнения каждого периода, миллисекунды (выполняет функцию запуска класса TimerTask или его расширения) Второй параметр: Когда должен запускаться таймер.В этом случае он запускается при вызове функции расписания.В следующем примере показана начальная 1 секунда после вызова функции расписания: timer.schedule(new Tasker(),1000,period); Третий параметр: миллисекунды между одним вызовом функции Tasker.run () и следующим вызовом.

Надеюсь, вы понимаете этот микротуод :),Если у вас возникли проблемы, обратитесь за более подробной информацией!

С уважением!

3 голосов
/ 31 августа 2011

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

...