Как отложить только цикл while?

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

 public class Panel extends javax.swing.JPanel  
{  
    int a=0;
    int b=0;
    public void paint(java.awt.Graphics g) 
    {     
        g.setColor(Color.GREEN);  
        g.fillRect(0,0,500,500); 
        g.setColor(Color.BLACK);  

        while( a<=500&&b<=500){
            g.fillRect(a,b,5,5);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ie) {}               
            a++;
            b++;

        }

    } 

сделать это в отдельной теме. тогда вы можете позволить этому потоку «спать», в то время как остальные продолжаются. например тема демона. это поток, который работает в фоновом режиме, не блокируя поток вашего приложения.

Stultuske 30.01.2019 14:03

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

khelwood 30.01.2019 14:05

Вы можете рисовать свою линию постепенно, но у Хелвуда есть идея получше.

DarceVader 30.01.2019 14:06

Используйте свинг Timer и в его периодическом методе обратного вызова сделайте a++; b++; Panel.this.repaint();

Joop Eggen 30.01.2019 14:26
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
5
86
1

Ответы 1

Вы неправильно понимаете, как работает Graphics. Вы не можете просто «отложить» рендеринг, нарисовав что-то позже. Это либо задержит ваш поток рендеринга, либо вообще не будет отображаться на экране.

Причина этого в том, что отрисовка всех ваших перекрашенных компонентов должна быть завершена до того, как будет сделан рендеринг. Однако, если вы постепенно рисуете линию, весь процесс будет ждать, пока цикл не завершится, чтобы программа продолжила работу (и чтобы отображалась линия). Думайте о методе рисования как о затворе камеры. Вы делаете быструю картинку, а не видео. Так что для того, чтобы что-то «двигалось» или медленно рисовалось, нужно поставить много картинок последовательно, как в кино.

На самом деле вам нужно периодически перерисовывать панель (вам нужна частота кадров). Так, например, если вы хотите отображать что-то близкое к 30 кадрам в секунду, вы можете сделать:

public class AutoUpdatedPanel extends javax.swing.JPanel {
    Thread t;
    float linePercent = 0f;

    public AutoUpdatedPanel () {
        t = new AutoUpdateThread();
        t.start();
    }

    public void paint(java.awt.Graphics g) {     
        g.setColor(Color.GREEN);  
        g.fillRect(0, 0, 500, 500); 
        g.setColor(Color.BLACK);  

        int linePos = (int) 5 * linePercent;
        g.fillRect(linePos, linePos, 5, 5);
    }

    public class AutoUpdateThread extends java.lang.Thread {
        public void run() {
            while (!isInterrupted()) {
                try {
                    Thread.sleep(33);
                } catch (InterruptedException e) {
                    // silent.
                }
                linePercent += .5f;
                linePercent = math.min(linePercent, 100f);
                AutoUpdatedPanel.this.repaint();
            }
        }
    }
}

Однако я бы посоветовал сделать рост строки по времени:

    ...

    public class AutoUpdateThread extends java.lang.Thread {
        public void run() {
            while (!isInterrupted()) {
                try {
                    Thread.sleep(33);
                } catch (InterruptedException e) {
                    // silent.
                }

                nowMillis = Calendar.newInstance().getTimeInMillis();
                long timeOffset = nowMillis - start;
                linePercent = (float) (.002d * timeOffset);
                linePercent = math.min(linePercent, 100f);
                AutoUpdatedPanel.this.repaint();
            }
        }
    }

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