Wie funktioniert JComponent.paintImmediately () - arbeiten in Java-Swing?
Mein Verständnis:
Im Gegensatz zu den meisten Komponenten/Operationen in Swing Aufruf von JComponent.repaint() ist thread-safe, d.h. wenn ein repaint Wunsch aus einem anderen thread (also nicht von EDT), der eigentlichen Malerei geschieht im EDT nur. Unter code-snippet veranschaulicht dies.
public class PaintingDemo {
public static void main(String[] args) {
final JFrame frame = new JFrame();
final JPanel p = new MyPanel();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
frame.add(p, BorderLayout.CENTER);
frame.setSize(200, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
new Thread("MyThread") {
public void run() {
while (true) {
//Below statements are important to show the difference
p.repaint();
p.paintImmediately(p.getBounds());
try {
Thread.sleep(1000);
} catch(Exception e) {}
}
}
}.start();
}
}
class MyPanel extends JPanel {
@Override
public void paint(Graphics g) {
System.out.println("paint() called in "+ Thread.currentThread().getName());
super.paint(g);
}
}
Aus der Ausgabe es ist bekannt, dass die Malerei erfolgt in EDT, wenn repaint() aufgerufen wird, unabhängig davon, aus welchem thread Sie aufgerufen wird - also keine Probleme. Aber im Fall von paintImmediately() - Malerei geschieht in dem selben thread, aus dem es aufgerufen wird.
Betrachten einen Fall, wo die EDT ist das ändern des Status einer Komponente und einem anderen thread (von denen paintImmediately() aufgerufen wird), ist die Malerei die gleiche Komponente.
Meine Frage:
Im Falle von paintImmediately(), wie ist die Synchronisation zwischen dem Event Dispatcher Thread (EDT) und anderen threads behandelt?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Meinem Verständnis, wenn Sie anrufen paintImmediately, rufen Sie den folgenden code:
So, es sei denn, dies ist nicht eine
JComponent
Sie am Ende aufrufen_paintImmediately()
die endet Aufrufpaint(Graphics)
schlägt die stack-trace-unter (gefangen von einem Stück code, das werde ich am Ende dieses post):Aber wenn Sie versuchen, fordern auch
repaint()
gleichzeitig (aus einem anderen Thread), sehen Sie, dass beide zur gleichen Zeit laufen (ich habe versucht, treten in den code mit debuger und Malerei nie aufgehört auftreten in dem anderen Thread) es scheint, dass bei den Java-code-Ebene gibt es nicht viel Synchronisation (zumindest konnte ich nicht vor Ort nichts). Also, wenn Sie am Ende in einer änderung des Komponentenstatus in der EDT, ich glaube, die Ergebnisse sind ziemlich unvorhersehbar, und Sie sollten vermeiden, eine solche situation mit allen Mitteln.Nur um zu veranschaulichen mein Punkt, ich habe versucht, ändern Sie den Zustand einer variable innerhalb der
paint
Methode, fügen Sie einesleep
erhöhen das Risiko von Kollisionen zwischen den 2 Threads (EDT und die anderen) und es obvisouly scheint, dass es keine Synchronisation zwischen den beiden Threads (dieSystem.err.println()
ausgegebennull
von Zeit zu Zeit).Nun möchte ich Fragen, warum Sie brauchen, um eine paintImmediately. Es sei denn, Sie blockieren die EDT, es gibt nicht so viele Gründe zu einer solchen Sache.
Unten ist der code, den ich verwendet, um zu testen, diese Dinge (ziemlich in der Nähe die man geschrieben in der Frage). Der code ist nur dazu da, um zu versuchen zu verstehen, was Los ist, nicht zu zeigen, wie Sie ausführen ordnungsgemäße Malerei noch keine gute Swing-Praxis.
JComponent
docs ReferenzpaintImmediately()
undrepaint(..)
wo als Quelle ist anders. Ich muss Fragen, wenn in deinem snippet würden wir nie überschreibenpaint(..)
einerJComponent
also, warum nicht Sie verwendenpaintComponent
(es scheint immer noch, um Ergebnisse zu reproduzieren)? Und eine andere Frage, warum wird die Erhöhung dersleep(int milis)
nicht erhöhen Kollisionen? Und auch, warum nennst dupaintImmediately
aus einem anderen thread als das EDT, (da sehe ich einmal genannt, auf der EDT nicht null werden kann)?paint
eher alspaintComponent
ich dachte nur, dass in dem Versuch zu sehen, wiepaintImmediately
schließlich fordertpaint
hinzufügen der zusätzlichen AufrufpaintComponent
im stack call unnötig war und die beobachteten Ergebnisse würden die gleichen bleiben. So war es nur entfernen Sie alle "Geräusche" aus den Informationen, und wie gesagt mein snippet es nicht illustrieren richtige Art und Weise zu verwenden Swing. Cheers 😉