Я пробовал 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++;
}
}
Вы не должны засыпать в потоке, рисующем ваш компонент, потому что ваше приложение зависит от того, что этот поток будет запущен. Вам нужно отделить обновление состояния и время от рендеринга. Настройте переменную на таймере в другом потоке и каждый раз перерисовывайте панель с новым состоянием.
Вы можете рисовать свою линию постепенно, но у Хелвуда есть идея получше.
Возможный дубликат Апплет Java Swing: как замедлить или отложить paint(), не замедляя работу всей программы
Используйте свинг Timer и в его периодическом методе обратного вызова сделайте a++; b++; Panel.this.repaint();




Вы неправильно понимаете, как работает 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();
}
}
}
сделать это в отдельной теме. тогда вы можете позволить этому потоку «спать», в то время как остальные продолжаются. например тема демона. это поток, который работает в фоновом режиме, не блокируя поток вашего приложения.