Warum ist paint()/paintComponent() nie aufgerufen wird?
Für die letzten zwei Tage habe ich versucht, verstehen wie Java-Griffe Grafiken, aber haben kläglich versagt, genau. Mein Hauptproblem ist das Verständnis genau, wie und Wann paint() (oder die neuere paintComponent() ) ist/aufgerufen werden soll.
In der folgende code, den ich gemacht, um zu sehen, wenn die Dinge geschaffen sind, wird die paintComponent() wird nie aufgerufen, wenn ich manuell einen Anruf hinzufügen, bis es mich oder Aufrufe von JFrame.paintAll()/JFrame.paintComponents().
Umbenannt habe ich die paint () - Methode paintComponent() in der Hoffnung, dass mein problem beheben würde es nie aufgerufen wird (auch bei repaint()), aber kein Glück.
package jpanelpaint;
import java.awt.*;
import javax.imageio.*;
import javax.swing.*;
import java.io.*;
import java.util.ArrayList;
public class ImageLoadTest extends JComponent {
ArrayList<Image> list;
public ImageLoadTest() {
list = new ArrayList<Image>();
try { //create the images (a deck of 4 cards)
for(String name : createImageFileNames(4)){
System.err.println(name);
list.add(ImageIO.read(new File(name)));
}
} catch (IOException e) { }
}
protected void paintComponent(Graphics g) {
int yOffset=0;
System.err.println("ImageLoadTest.paintComponent()");
for(Image img : list) {
g.drawImage(img, 0, yOffset, null);
yOffset+=20;
}
}
public static void main(String args[]) throws InterruptedException {
JFrame frame = new JFrame("Empty JFrame");
frame.setSize(new Dimension(1000, 500));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
Thread.sleep(1000);
frame.setTitle("Loading images");
ImageLoadTest ilt = new ImageLoadTest();
frame.add(ilt);
//update the screen
//DOESN'T WORK. only works if I call frame.paintAll(frame.getGraphics())
ilt.repaint();
frame.repaint();
Thread.sleep(1000);
frame.setTitle("Setting background");
ilt.setBackground(Color.BLACK);
//update the screen - DOESN'T WORK even if I call paintAll ..
ilt.repaint();
frame.repaint();
//have to call one of these to get anything to display
// ilt.paintComponent(frame.getGraphics()); //works
frame.paintComponents(frame.getGraphics()); //works
}
//PRIVATE HELPER FUNCTIONS
private String[] createImageFileNames(int count){
String[] fileNames = new String[count];
for(int i=0; i < count; i++)
fileNames[i] = "Cards" + File.separator + (i+1) + ".bmp";
return fileNames;
}
}
Du musst angemeldet sein, um einen Kommentar abzugeben.
Einer der Gründe, die paintComponent() nicht aufgerufen wird in der original code ist, da die Komponente hat eine "null-Größe" und die RepaintManger ist klug genug, nicht zu versuchen, etwas zu malen ohne Größe.
Den Grund der Neuordnung der code funktioniert, weil, wenn Sie die Komponente hinzufügen, um den frame und dann den frame sichtbar ist der layout-manager aufgerufen wird, um das layout der Komponente. Standardmäßig wird ein Rahmen verwendet ein BorderLayout und standardmäßig eine Komponente Hinzugefügt wird, um die Mitte des BorderLayout was passiert, geben den ganzen Raum zur Verfügung, um die Komponente, so wird es gestrichen.
Jedoch, ändern Sie die layout-manager der content-Bereich ein FlowLayout, würden Sie immer noch ein problem haben, weil ein FlowLayout Hinsicht die bevorzugte Größe der Komponente, die gleich null ist.
So, was Sie wirklich tun müssen, ist, weisen Sie eine bevorzugte Größe, um Sie Ihr Gerät so layout-Manager können Ihre Arbeit tun.
Ein wichtiges Problem, hier ist Sie nicht aktualisieren Sie Ihre swing-Komponenten auf dem Event-Dispatch-Thread (EDT). Versuchen Sie das einwickeln der gesamte code in der main-Methode im folgenden:
Auch: fügen Sie Ihre ImageLoadTest zu dem frame genau vor der Einstellung der frame sichtbar. Die Grundlage dafür ist ein schnelles flüchtiges Lesen der code-ich werde es Lesen weiter und sehen, was ich finden kann.
EDIT:
Folgen mein original-Gutachten vor, und vereinfachen Sie Ihre main-Methode wie folgt Aussehen und Ihre paintComponent() aufgerufen wird:
Ich würde auch Lesen, mit Timer durchführen, animation sowie Allgemeine Swing-event-dispatching und wie/Wann überschreiben verschiedenen malen Methoden.
http://java.sun.com/products/jfc/tsc/articles/painting/
http://java.sun.com/docs/books/tutorial/uiswing/misc/timer.html
http://java.sun.com/docs/books/tutorial/uiswing/concurrency/dispatch.html
java.awt.EventQueue.
]invokeLater
macht es für mich arbeiten.revalidate
nachadd
wie beschrieben in die API docs füradd
.)javax.swing.Timer
wäre der Weg zu gehen. Aber die Swing-code kann nicht bleiben aus der EDT.Machen Tom Hawtin - tackline glücklich. Ich schrieb wieder einmal
Es gibt mehrere Dinge, die ich geändert (überprüfen Sie die Linien mit der//new
Kommentar)Schrieb es völlig
ImageLoadTest.java
) und eine Datei, um es zu testen (Tester.java
)Verbesserungen auf original-Plakate code
ImageLoadTest
Konstruktor (super()
)setPreferredSize()
Komponente im Konstruktor. Wenn die Größe nicht festgelegt ist swing natürlich nicht zu malen Ihre Komponente. bevorzugt basiert die Größe auf max. Breite der Bilder und auf die Summe aller Bild-Höhensuper.paintComponent(g)
im übersteuertenpaintComponent()
geändert
paintComponent
automatisch BasisyOffset
auf die Höhe der Bilder gezogenGUI Initialisierung erfolgt auf der EDT
sleep()
zu veranschaulichen, laden und das laden der Bilder sehr lange dauern kannSwingWorker
's verwendetworker
wartet, setzt dann neue Titel und dann lädt Bilderworker
imdone()
schließlich fügt die Komponente derJFrame
und zeigt Sie an. Zusätzliche Komponente zum Inhaltsbereich derJFrame
wie beschrieben in JFrame api. Und wie in javadoc notwendig, Aufrufvalidate()
aufJFrame
nach dem Aufrufadd()
alsJFrame
ist eine bereits sichtbare container, deren Kinder geändert.JPanel
als baseclass fürImageLoadTest
zu behebensetBackground()
die ich nicht bekommen konnte, mit zu arbeitenJComponent
.Damit Ihre größten Probleme dort, wo Sie nicht festlegen, wird die bevorzugte Größe der Komponente ist, und dass Sie nicht nennen
validate()
auf dieJFrame
nach etwas hinzufügen zu der bereits sichtbaren container.Sollte diese Arbeit
jpanelpaint/ImageLoadTest.java
Tester.java
Diese waren die wichtigsten Probleme, die mit dem ursprünglichen code, der verursacht, dass es nicht funktioniert:
setBackground () - Aufruf nicht funktioniert)
Hatte die oben, es ist wirklich nicht egal, wenn der Aufruf der Methode paintComponent bzw. paint, beide Schienen zu arbeiten, solange ich in Erinnerung zu rufen, den super-Konstruktor an den start.
Diese info war zusammengesetzt aus dem, was @jitter, @tackline und @camickr schrieb, so ein großes Lob!
P. S. Keine Ahnung, ob die Beantwortung Ihrer eigenen Frage als schlechte form, aber da die Informationen, die ich brauchte, war zusammengesetzt aus mehreren Antworten, ich dachte, der beste Weg war upmodding die anderen Antworten und schreiben eine Summe wie diese.
Ich empfehle die Lektüre der ersten paar Kapitel von "Filthy Rich Clients". Ich war mit Schaukel für Jahre, aber nur nach der Lektüre dieses Buches habe ich endlich vollständig zu verstehen, wie die Java-Malerei-Mechanismus arbeitet.