Свинг-персонал - пассивный двигатель перекраски. То есть, он будет обновляться только тогда, когда это требуется. RepaintManager
также оптимизирован для объединения нескольких репрессий до нескольких событий перерисовки, которые, по его мнению, требуются.
Это значит, что вы можете сделать заявку на номер repaint
, но нет гарантии, когда и когда произойдет перекраска.
Это делается главным образом для оптимизации производительности.
Отъезд Painting in AWT and Swing для получения более подробной информации.
Из-за своей природы repaint
является потокобезопасным. repaint
запрашивает RepaintManager
, чтобы отправить событие рисования в очередь событий. Эта очередь обрабатывается Диспетчерством событий, то есть вам не нужно синхронизировать repaint
с EDT самостоятельно.
Следующий пример демонстрирует эту идею. Он обеспечивает простой слайдер, который сбрасывает счетчики краски и устанавливает задержку между запросами repaint
.
задержка Нить 0 миллисекунд ...
задержка Нить 2 секунды
Как вы можете видеть. При 0 миллисекундах (что фактически вы делаете в цикле) количество фактических красок не соответствует числу запросов на перерисовку, но при задержке в 2 секунды фактические краски и запросы краски почти равны (я думаю, что добавляется один из перерисовки, сделанных слайдером).
Фактически, в моем тестировании, около 100 миллисекунд, я смог получить его примерно равным. Я даже попробовал 5 миллисекунд и получил баланс.
Что фактическая краска делает и нагрузка на EDT будет также влиять на эти результаты ...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class RepaintTest {
public static void main(String[] args) {
new RepaintTest();
}
public RepaintTest() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private int paintRequests;
private int paints;
private int delay = 0;
public TestPane() {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
paintRequests++;
try {
Thread.sleep(delay);
} catch (InterruptedException exp) {
}
System.out.println("tick");
repaint();
}
}
});
t.setDaemon(true);
setLayout(new BorderLayout());
final JSlider slider = new JSlider();
slider.setMinimum(0);
slider.setMaximum(2000);
slider.setPaintTicks(true);
slider.setMajorTickSpacing(100);
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
delay = slider.getValue();
paintRequests = 0;
paints = 0;
}
});
slider.setValue(0);
add(slider, BorderLayout.SOUTH);
t.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
paints++;
String text = "Paints = " + paints + "; Paint Requests = " + paintRequests;
Graphics2D g2d = (Graphics2D) g.create();
FontMetrics fm = g2d.getFontMetrics();
int x = (getWidth() - fm.stringWidth(text))/2;
int y = ((getHeight() - fm.getHeight())/2) + fm.getAscent();
g2d.drawString(text, x, y);
g2d.dispose();
}
}
}
Что именно вы пытаетесь достичь? Какой смысл перерисовывать JFrame 10 раз в цикле? –
'repaint()' запросы объединяются вместе, если незавершенный запрос уже присутствует в 'Event Dispatcher Thread'. Кроме того, попробуйте сделать внутри 'paintComponent (...)' метод 'JPanel' вместо прямого рисования на контейнере верхнего уровня. –
@JBNizet Я ничего не пытался добиться. Я пытался проверить, вызван ли метод repaint() запуском. и сколько раз его вызывали. –