Warum wird paint () / paintComponent () nie aufgerufen?

8

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%     
oligofren 04.11.2009, 19:53
quelle

5 Antworten

3

Das waren die Hauptprobleme mit dem ursprünglichen Code, der dazu führte, dass es nicht funktionierte:

  1. Aufruf von validate () nach einer Operation add ()
  2. nicht
  3. nicht die bevorzugte Größe der Komponente festlegen.
  4. Aufruf von super.paintComponent () beim Überschreiben nicht (dies hat den setBackground () -Aufruf funktioniert nicht)
  5. Ich musste JPanel erben, damit es angezeigt wird. Weder Component noch JComponent waren ausreichend, damit der Aufruf von setBackground () auch bei Fixierung von Punkt 3 funktionieren konnte.

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.

    
oligofren 05.11.2009, 07:04
quelle
11

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.

    
camickr 04.11.2009 21:21
quelle
4

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.

Ссылка

Ссылка

Ссылка

    
Chris B. 04.11.2009 20:06
quelle
4

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

  • Aufteilen in eine saubere neue Komponentendatei ( ImageLoadTest.java ) und eine Datei zum Testen ( Tester.java )

Verbesserungen am ursprünglichen Postercode

  • Aufruf des Konstruktors des Elternteils in ImageLoadTest Konstruktor ( super() )
  • lieferte den zweiten Konstruktor, um die Liste der Bilder festzulegen, welche Komponente angezeigt werden sollte
  • WICHTIG: Aufruf von 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
  • Aufruf an 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

  • als Originalcode, der auf der Verwendung von 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
  • nach Abschluss fügt die 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.

  • zweiter Arbeiter macht nur noch mehr Wartezeiten und setzt die Hintergrundfarbe auf Schwarz
  • verwendet 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%     
jitter 04.11.2009 21:41
quelle
2

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.

    
Steve McLeod 04.11.2009 20:22
quelle

Tags und Links