Печать форм Java с задержкой

Я пытаюсь создать программу, которая решает популярную игру Towers of Hanoi. Мне удалось распечатать диски и колышки, но я хочу, чтобы диски печатались с задержкой. Например, я хочу, чтобы диск 7 печатался, а затем диск 6 печатался через 1 секунду. Я попытался сделать это, уложив его в режим сна, но все, что он делает - это задерживает отображение всего кадра, как мне заставить его отображать форму с задержкой. Я приложил свой код, спасибо за любую помощь!

package towersofhanoi;
import javax.swing.*;
import java.awt.*;

/*g.fillOval(60 = horizontal distance , 540= vertical distance, 400 = width, 60 = height) */

public class TowersOfHanoi extends JPanel {
    public static void main(String[]args){
        //Print the shapes and frame
        TowersOfHanoi drawRectangle = new TowersOfHanoi();
        JFrame frame = new JFrame("Towers of Hanoi");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(drawRectangle);
        frame.setSize(1250, 800);
        frame.setVisible(true);
    }
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        Color pegs = new Color (251, 129, 56);
        g.setColor(pegs);

        //peg 1
        g.fillRect(250, 300, 25, 450);
        //peg 2
        g.fillRect(600, 300, 25, 450);
        //peg 3
        g.fillRect(950, 300, 25, 450);
        //bottom
        g.fillRect(200, 700, 825, 50);
        //create a color for circles
        Color circles = new Color (176,56, 251);
        //cirle 7 (Labeled from bottom to top)
        g.setColor(circles);
        g.fillOval(60, 640, 400, 60);
        g.setColor(Color.BLACK);
        g.drawOval(60, 640, 400, 60);
        try {
            Thread.sleep(1000);
        }
        catch (InterruptedException ie) {

        }
        //circle 6
        g.setColor(circles);
        g.fillOval(85, 580, 350, 60);
        g.setColor(Color.BLACK);
        g.drawOval(85, 580, 350, 60);
        try {
            Thread.sleep(1000);
        }
        catch (InterruptedException ie) {

        }
        //circle 5
        g.setColor(circles);
        g.fillOval(110, 520, 300, 60);
        g.setColor(Color.BLACK);
        g.drawOval(110, 520, 300, 60);
        //circle 4
        g.setColor(circles);
        g.fillOval(135, 465, 250, 55);
        g.setColor(Color.BLACK);
        g.drawOval(135, 465, 250, 55);
        //circle 3
        g.setColor(circles);
        g.fillOval(160, 420, 200, 45);
        g.setColor(Color.BLACK);
        g.drawOval(160, 420, 200, 45);
        //circle 2
        g.setColor(circles);
        g.fillOval(185, 380, 150, 40);
        g.setColor(Color.BLACK);
        g.drawOval(185, 380, 150, 40);
        //circle 1
        g.setColor(circles);
        g.fillOval(210, 345, 100, 35);
        g.setColor(Color.BLACK);
        g.drawOval(210, 345, 100, 35);
    }
}

3 ответа

Решение

Моя рекомендация

  • разделить рисование в paintComponent() на 3 составляющие части, которые ранее были разделены операторами сна
  • Используйте состояние внутри объекта TowersOfHanoi, чтобы контролировать то, что должно быть нарисовано, я использовал простой счетчик
  • Используйте javax.swing.Timer, чтобы обновить счетчик и запросить перерисовку.

Заметки

  • Вы не можете спать в потоке пользовательского интерфейса. Swing является однопоточным, и это остановит обработку событий.
  • javax.swing.Timer автоматически запускает обратный вызов, который вы даете ему в потоке пользовательского интерфейса.
  • paintComponent() может вызываться несколько раз, если окна изменяются в размерах и т. д., поэтому важно сделать его независимым, поэтому я использую счетчик.

Рабочий пример

public class TowersOfHanoi extends JPanel {

    private int clock = 0;
    private Color circles = new Color(176, 56, 251);

    public static void main(String[] args) {
        // Print the shapes and frame
        TowersOfHanoi drawRectangle = new TowersOfHanoi();
        JFrame frame = new JFrame("Towers of Hanoi");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(drawRectangle);
        frame.setSize(1250, 800);
        frame.setVisible(true);

        Timer timer = new Timer(1000, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                drawRectangle.nextFrame();
                drawRectangle.repaint();
            }
        });
        timer.setRepeats(true);
        timer.start();
    }

    public void nextFrame() {
        clock++;
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        frame1(g);
        if (clock >= 1) {
            frame2(g);
        }
        if (clock >= 2) {
            frame3(g);
        }
    }

    private Color frame1(Graphics g) {
        Color pegs = new Color(251, 129, 56);
        g.setColor(pegs);

        // peg 1
        g.fillRect(250, 300, 25, 450);
        // peg 2
        g.fillRect(600, 300, 25, 450);
        // peg 3
        g.fillRect(950, 300, 25, 450);
        // bottom
        g.fillRect(200, 700, 825, 50);
        // create a color for circles
        // cirle 7 (Labeled from bottom to top)
        g.setColor(circles);
        g.fillOval(60, 640, 400, 60);
        g.setColor(Color.BLACK);
        g.drawOval(60, 640, 400, 60);
        return circles;
    }

    private void frame2(Graphics g) {
        // circle 6
        g.setColor(circles);
        g.fillOval(85, 580, 350, 60);
        g.setColor(Color.BLACK);
        g.drawOval(85, 580, 350, 60);
    }

    private void frame3(Graphics g) {
        // circle 5
        g.setColor(circles);
        g.fillOval(110, 520, 300, 60);
        g.setColor(Color.BLACK);
        g.drawOval(110, 520, 300, 60);
        // circle 4
        g.setColor(circles);
        g.fillOval(135, 465, 250, 55);
        g.setColor(Color.BLACK);
        g.drawOval(135, 465, 250, 55);
        // circle 3
        g.setColor(circles);
        g.fillOval(160, 420, 200, 45);
        g.setColor(Color.BLACK);
        g.drawOval(160, 420, 200, 45);
        // circle 2
        g.setColor(circles);
        g.fillOval(185, 380, 150, 40);
        g.setColor(Color.BLACK);
        g.drawOval(185, 380, 150, 40);
        // circle 1
        g.setColor(circles);
        g.fillOval(210, 345, 100, 35);
        g.setColor(Color.BLACK);
        g.drawOval(210, 345, 100, 35);
    }

}

Возможно, вам следует реструктурировать свой код так, чтобы компонент рисования отображал текущее состояние системы колышков и колец. Затем используйте таймер Swing для вызова метода, который перемещает состояние системы, а затем вызывает repaint().

Вы пытались использовать Caldender() или же System.currentTimeMillis()? Если вы это сделаете, вы можете получить текущее время. После того, как вы получили время, сделайте while цикл, чтобы проверить, сколько сейчас времени. Когда вы делаете LastTime - Now, чтобы проверить, сколько времени прошло.

Этот код не проверен, (но он должен работать).

long lastTime = System.currentTimeMillis();

while(true){

   long now = System.currentTimeMillis();

   if(lastTime - now == [YOUR PREFFERD WAITING TIME IN MS]){
      break;
   }
}

А теперь нарисуйте свою графику.

Другие вопросы по тегам