Seit zwei Tagen versuche ich zu verstehen , wie Java mit Grafiken umgeht, aber dabei kläglich versagt habe. Mein Hauptproblem ist, genau zu verstehen, wie und wann paint () (oder die neuere paintComponent ()) aufgerufen wird / sollte.
Im folgenden Code, den ich gemacht habe, um zu sehen, wann Dinge erstellt werden, wird paintComponent () niemals aufgerufen, es sei denn, ich füge manuell einen Aufruf selbst hinzu oder rufe JFrame.paintAll () / JFrame.paintComponents () auf.
Ich habe die paint () -Methode in paintComponent () umbenannt, in der Hoffnung, dass mein Problem, dass es nie aufgerufen wird, behoben wird (selbst bei repaint ()), aber kein Glück.
%Vor%Das waren die Hauptprobleme mit dem ursprünglichen Code, der dazu führte, dass es nicht funktionierte:
Nachdem ich das obige getan hatte, war es wirklich egal, ob ich die Methode paintComponent oder paint aufrufen würde, beide schienen so lange zu funktionieren, wie ich mich daran erinnerte, den Superkonstruktor am Anfang aufzurufen.
Diese Info wurde zusammengestellt aus was @jitter, @tackline und @camickr geschrieben hat, also großes Lob!
P.S. Keine Ahnung, ob die Beantwortung Ihrer eigenen Frage eine schlechte Form ist, aber da die Informationen, die ich brauchte, aus mehreren Antworten zusammengesetzt wurden, dachte ich, der beste Weg wäre, die anderen Antworten zu verbessern und so eine Zusammenfassung zu schreiben.
Einer der Gründe, warum paintComponent () nicht im Originalcode aufgerufen wird, ist, dass die Komponente eine "Nullgröße" hat und der RepaintManger schlau genug ist, etwas ohne Größe zu malen.
Der Grund für die Neuordnung des Codes liegt darin, dass beim Hinzufügen der Komponente zum Frame und anschließendem Anzeigen des Frames der Layout-Manager zum Layout der Komponente aufgerufen wird. Standardmäßig verwendet ein Frame ein BorderLayout und standardmäßig wird eine Komponente zur Mitte des BorderLayouts hinzugefügt, was dazu führt, dass der gesamte der Komponente zur Verfügung stehende Platz zur Verfügung gestellt wird, damit sie bemalt wird.
Wenn Sie jedoch den Layout-Manager des Inhaltsbereichs als FlowLayout festlegen, liegt immer noch ein Problem vor, da ein FlowLayout die bevorzugte Größe der Komponente, die Null ist, respektiert.
Sie müssen also Ihrer Komponente eine bevorzugte Größe zuweisen, damit Layout-Manager ihre Arbeit erledigen können.
Ein Hauptproblem besteht darin, dass Sie Ihre Swing-Komponenten nicht auf dem Thread für den Ereignisversand aktualisieren (EDT) . Versuchen Sie, den gesamten Code in Ihrer Hauptmethode wie folgt zu umhüllen:
%Vor%Außerdem: fügen Sie Ihren ImageLoadTest zum Rahmen hinzu, bevor Sie den Rahmen sichtbar machen. Dies basiert auf einem schnellen flüchtigen Lesen des Codes - ich werde es weiterlesen und sehen, was ich sonst noch finden kann.
BEARBEITEN:
Folgen Sie meinem ursprünglichen Ratschlag und vereinfachen Sie Ihre Hauptmethode so, dass sie wie folgt aussieht und Ihre paintComponent () aufgerufen wird:
%Vor%Ich würde auch über die Verwendung von Timern lernen, um Animationen durchzuführen, sowie allgemeine Swing Event-Dispatching und wie / wann verschiedene Paint-Methoden zu überschreiben.
Um Tom Hawtin - Tackline glücklich zu machen. Ich schrieb noch einmal um
Es gibt verschiedene Dinge, die ich geändert habe (überprüfe die Zeilen mit dem Kommentar //new
)
Rewrote es vollständig
ImageLoadTest.java
) und eine Datei zum Testen ( Tester.java
) Verbesserungen am ursprünglichen Postercode
ImageLoadTest
Konstruktor ( super()
) setPreferredSize()
der Komponente im Konstruktor. Wenn Größe nicht eingestellt wird, schwingt natürlich Ihre Komponente nicht. bevorzugte Größe basiert auf max. Breite aller Bilder und Summe aller Bildhöhen super.paintComponent(g)
in overriden paintComponent()
hat paintComponent
geändert, um yOffset
automatisch auf die Höhe der gezeichneten Bilder zu setzen
GUI-Initialisierung auf EDT durchgeführt
sleep()
basiert, um das Laden und Laden von Bildern zu veranschaulichen, kann sehr lange dauern, bis SwingWorker
verwendet werden. worker
wartet, setzt dann einen neuen Titel und lädt dann Bilder worker
in done()
die Komponente schließlich zu JFrame
hinzu und zeigt sie an. Dem Inhaltsbereich von JFrame
wurde eine Komponente hinzugefügt, wie in JFrame api. Und wie in javadoc notwendig gemacht Aufruf nach validate()
auf JFrame
nach Aufruf von add()
, da die JFrame
ist ein bereits sichtbar Container, der Kinder geändert wurde. javdoc Zitat aus
validate()
Die Validierungsmethode wird verwendet, um a zu verursachen Container, um seine Unterkomponenten auszulegen nochmal. Es sollte dann aufgerufen werden Unterkomponenten des Containers werden geändert (hinzugefügt oder entfernt von der Container oder layoutbezogen Informationen geändert) nach dem Container wurde angezeigt.
JPanel
als Basisklasse für ImageLoadTest
, um setBackground()
zu fixieren, was ich nicht mit JComponent
erreichen konnte. Also deine Hauptprobleme, wo du nicht die bevorzugte Größe der Komponente festgelegt hast und validate()
nicht auf der JFrame
aufgerufen hast, nachdem du etwas zu dem bereits sichtbaren Container hinzugefügt hast.
Dies sollte funktionieren
jpanelpaint / ImageLoadTest.java
%Vor%Tester.java
%Vor%Ich empfehle die ersten paar Kapitel von "Filthy Rich Clients" zu lesen. Ich habe Swing jahrelang benutzt, aber erst nachdem ich dieses Buch gelesen hatte, verstand ich endlich genau, wie Javas Malmechanismus funktioniert.