Swing repaint() ruft paintComponent(g1d) nicht auf

liann

Mitglied
Hallo, ich habe gerade vermutlich einen blackout, aber nach 40 minuten im code und internet suchen , finde ich echt nichts 🤯.
repaint() wird bei dem Label augerufen, jedoch paintComponent(g1d) nicht:
Java:
// JLabel object draw
draw = new JLabel() {
            @Override
            protected void paintComponent(Graphics g1d) {
                super.paintComponent(g1d);
                draw((SunGraphics2D) g1d);
                System.out.println("painted!");
                // wird nicht aufgerufen
            }

            @Override
            public void repaint() {
                super.repaint();
                System.out.println("repainted draw!"); // wird immer aufegrufen
            }
        };

private void draw(SunGraphics2D g2) {
        g2 = (SunGraphics2D) g2.create();
        drawBackground(g2);
        drawGames(g2);
        g2.dispose();
// auch ohne create() und somit auch ohne dispose() klappt es nicht
    }

private void drawGames(Graphics2D g2) {
        for (Drawable drawable : games)
            if (drawable != null)
                drawable.draw(g2);
        for (Drawable drawable : games)
            if (drawable != null)
                drawable.drawInfoText(g2);
    // hier müssten keine Probleme sein: die gleichen methoden werden in anderen Klassen auch aufgerufen
    }

    private void drawBackground(SunGraphics2D g2) {
        g2.setColor(Color.darkGray);
        g2.fillRect(0, 0, getWidth(), getHeight());
    }
Wo ist mein Fehler??
 

user30

Mitglied
1. die super-Aufrufe sollten immer die letzte Anweisung sein,
2. repaint() solltest du nicht überschreiben, sondern nur aufrufen,
3. dispose() muss imho nicht aufgerufen werden,
 

liann

Mitglied
repaint() solltest du nicht überschreiben, sondern nur aufrufen,
gilt das für alle oder nur für das label zum zeichnen? Denn in meinem JFrame wird repaint() überschrieben mit:
Java:
@Override
public void repaint() {
    super.repaint();
    draw.repaint();
}
Das überschreiben im Label war nur da, um mir selber sicher zu gehen, dass die methode aufgerufen wird, was sie wird.
Die anderen Sachen habe ich kurz geändert, jedoch klappt es immer noch nicht
 

liann

Mitglied
Okay also ich habe jetzt ein mögliches Problem gefunden, wenn ich nämlich repaint() per knopfdruck aufrufe, klappt alles. Dann müsste es an folgender Methode liegen. Ich weiß aber nicht, was daran falsch sein sollte. Ich will nämlich einen Übergang zwischen zwei JFrames erzeugen, der flüssig ist.
Java:
 public void transformTo(JFrame jframe) {
        while (jframe.getWidth() != getWidth() || jframe.getHeight() != getHeight()) {
            int x = jframe.getWidth() - getWidth();
            int y = jframe.getHeight() - getHeight();
            if (x < 0) {
                x++;
            } else if (x > 0) {
                x--;
            }
            if (y < 0) {
                y++;
            } else if (y > 0) {
                y--;
            }
            setSize(jframe.getWidth() - x, jframe.getHeight() - y);
            setLocationRelativeTo(null);
            repaint(); // ruft nicht warum auch immer paintComponent(g1d)
        }
}
     private void addBtn(){
         JButton b = new JButton();
         add(b);
         b.addActionListener(e -> repaint()); // ruft paintComponent(g1d) auf
     }
 

mihe7

Top Contributor
Ich weiß aber nicht, was daran falsch sein sollte. Ich will nämlich einen Übergang zwischen zwei JFrames erzeugen, der flüssig ist.
Das Problem ist, dass Deine transferTo-Methode im Event Dispatch Thread (EDT, aka UI-Thread) ausgeführt wird. So lange Deine Schleife läuft, wird sich Dein UI nicht aktualisieren. Du muss dafür sorgen, dass die Schleife in einem anderen Thread ausgeführt wird, während die Methoden, die das UI verändern, im EDT laufen. Das repaint() am Ende der Schleife dürfte überflüssig sein, da das Fenster bei einer Größenänderung sowieso neu gezeichnet werden muss.

Je nach Implementierung musst Du dann berücksichtigen, dass nun zwei Threads im Spiel sind und sich die Größenänderung nicht sofort auswirkt. D. h. die Prüfung zu Beginn der Schleife würde ohne weitere Maßnahmen ggf. auf die alten Werte zugreifen.

Die einfachste Variante scheint mir hier ein Swing-Timer zu sein, auch wenn dieser nicht besonders präzise ist.
 
K

kneitzel

Gast
Jetzt möchte ich auch einfach mal ein paar Punkte kommentieren.

1. die super-Aufrufe sollten immer die letzte Anweisung sein,
2. repaint() solltest du nicht überschreiben, sondern nur aufrufen,
3. dispose() muss imho nicht aufgerufen werden,

1. Also an welcher Stelle die super Aufrufe erfolgen ist nicht vorgegeben. Die Frage ist halt, ob und an welcher Stelle die Funktionalität gewünscht wird. Das ist also nicht so pauschal ausdrückbar.

2. In der Regel reicht es, repaint nur zu nutzen. Aber wenn die Funktionalität erweitert werden soll, dann spricht natürlich auch nichts dagegen, repaint zu überschreiben. Die Frage ist also: was ist dieses draw? Die Logik scheint mir ein wenig verrückt zu sein, aber generell spricht nichts dagegen, auch an der Stelle etwas einzufügen. Aber darauf gehe ich später noch einmal ausführlicher ein.

3. dispose() ist richtig, denn er hat ein create(), sprich er erzeugt die Graphics Instanz und muss daher diese auch entsorgen.
Aber wozu dient der create() Aufruf? Der ist aus meiner Sicht unnötig. Die Instanz, die übergeben wird, kann direkt verwendet werden.

Generell ist wichtig, die Grundlagen zu verstehen. Was passiert da denn, wenn ein invalidate, repaint oder ähnliches gemacht wird - sei es aktiv im code oder indirekt durch das System?

Erst einmal: Was passiert da in so einem Programm? Man hat, wenn man es einfach betrachtet, einfach eine Schleife in einem Thread (EDT Thread), die Events abarbeitet. Events können sein: Tastendrücke, Mausclicks, Mausbewegungen, Anforderungen, etwas zu tun, ... Das ist also wichtig, denn ein repaint ist eigentlich nichts anderes als: Wie packen ein Event an das Fenster in die Eventqueue, die sagt: Mal dich neu. Das findet somit erst statt, wenn das Event bearbeitet werden kann. So lange die Applikation also nicht zu dem Event kommt, passiert nichts. (Siehe Antwort von @mihe7)

Wenn ein Betriebssystem Fenster darstellt, dann interessiert es sich nicht für den Inhalt. Für die Darstellung des Inhalts ist das Programm zuständig. Was aber das Betriebssystem interessiert ist: Ist das Fenster korrekt dargestellt. Das ist etwas, das sich z.B. verändert, wenn ein anderes Fenster das Fenster Deiner Applikation überdeckt. Dann ist klar: Dann ist der Inhalt des Fensters in dem überlappten Bereich nicht mehr gültig. Das kann man auch erreichen, indem man invalidate aufruft und den Bereich angibt, der nicht mehr gültig sein soll.
Wenn das Betriebssystem nun so einen Bereich erkennt, dann folgt daraus, dass das Betriebssystem das Fenster auffordert, diesen Bereich neu zu malen.

Wenn man nun ein Programm schreibt, dann kann man das nutzen: immer, wenn sich Daten ändern, dann müssen die dargestellt werden. Also macht man z.B. ein repaint Aufruf auf einem Fenster.
Das sorgt dann dafür, dass das ganze Fenster incl. aller Controls und so, neu gemalt wird. Um die Childs wird sich automatisch gekümmert. Wenn das "draw" also sowas wie ein Child Element ist, ist dieses Überschreiben unnötig.
Und wenn eine Applikation mehrere Fenster hat, dann ist auch denkbar: Wenn ich beim Hauptfenster repaint aufrufe, dann soll auch auf einem / allen anderen Fenster repaint aufgerufen werden. Das wäre eine valide Anforderung, die dann z.B. in einer so überschriebenen repaint Methode resultieren könnten.
 

liann

Mitglied
Erst einmal danke für di ganzen Antworten!
Heißt das jetzt, dass repaint() einfach ignoriert wird, da gerade eine andere Aufgabe ausgeführt wird? Und ich mache den Übergang so, dass ich 2 Klassen habe, die beide von JFrame erben. Das eine ist sichtbar, das andere nicht. Wenn ich das Fenster "wechseln" will, zum Beispiel nach einem Mausklick von dem User, rufe ich beim Hauptfenster transformTo(secondWindow) auf. Allerdings wird nur ein kleines rechteck gezeichnet, was der größe von vorher entspricht. Wenn ich jetzt das Fenster wirklich übermalen will, muss ich also was machen? Oder soll ich eine ganz andere Methode für den Zweck schreiben, die irgendwas anders macht?
 

mihe7

Top Contributor
Heißt das jetzt, dass repaint() einfach ignoriert wird, da gerade eine andere Aufgabe ausgeführt wird?
Ja, so lange die Aufgabe läuft. Stell Dir einen Stapel mit Aufgaben vor, der abgearbeitet werden muss. Swing (eigentlich AWT) arbeitet diesen Stapel ab. Eine dieser Aufgaben ist Deine Methode, die irgendwann mal drankommt. In dieser Methode erzeugst Du nun neue Aufgaben (repaint() -> mal mir das Fenster neu), die landen ganz unten im Stapel. Wenn Deine Methode (Aufgabe) erledigt ist, kommt die nächste dran, bis irgendwann dann auch das repaint() an der Reihe ist. Hinzu kommt, dass der Spaß intern bzgl. der Anzeige optimiert wird (das aber nur nebenbei).

Hier mal was zusammengeschustert:
Java:
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.Point;

import javax.swing.*;

public class Test {
    static class FrameTransform {
        public static final int DEFAULT_DELAY = 20;
        private final Timer timer;
        private final JFrame frame;
        private final Dimension from;
        private final Dimension to;
        private final int duration;

        private long startTime;

        public FrameTransform(JFrame frame, Dimension from, Dimension to, 
                              int duration) {
            this(frame, from, to, duration, DEFAULT_DELAY);
        }

        public FrameTransform(JFrame frame, Dimension from, Dimension to, 
                              int duration, int delay) {
            this.frame = frame;
            this.from = from;
            this.to = to;
            this.duration = duration;

            timer = new Timer(delay, e -> animate());
            timer.setRepeats(true);
        }

        public void start() {
            this.startTime = System.currentTimeMillis();
            frame.setVisible(true);
            frame.toFront();
            timer.start();
        }

        private void animate() {
            long elapsed = System.currentTimeMillis() - startTime; 
            if (elapsed >= duration) {
                resize(to);
                timer.stop();
            }

            int widthDiff = to.width - from.width;
            int heightDiff = to.height - from.height;
            int relevantDiff = Math.abs(widthDiff) > Math.abs(heightDiff) ?
                   widthDiff : heightDiff;

            double fraction = ((double) relevantDiff) / duration;

            int width = from.width + bound(elapsed * fraction, widthDiff);
            int height = from.height + bound(elapsed * fraction, heightDiff);

            resize(new Dimension(width, height));
        }

        private int bound(double value, int boundary) {
            return (int) (boundary < 0 
                    ? Math.max(boundary, value)
                    : Math.min(boundary, value));
        }

        private void resize(Dimension size) {
            Point center = GraphicsEnvironment
                     .getLocalGraphicsEnvironment()
                     .getCenterPoint();
                  
            int x = center.x - size.width / 2;
            int y = center.y - size.height / 2;
            frame.setBounds(x, y, size.width, size.height);
        }
    }

    private final Dimension defaultSize = new Dimension(800, 600);
    private final Dimension resizedSize = new Dimension(200, 200);


    public void run() {
        final JFrame frame = createFrame("The Frame");

        JButton button = new JButton("Animate");
        button.addActionListener(e -> {
            Dimension size = frame.getSize();
            Dimension from = size.equals(defaultSize) ? defaultSize : resizedSize;
            Dimension to = size.equals(defaultSize) ? resizedSize : defaultSize;

            new FrameTransform(frame, from, to, 5000).start();
        });

        frame.add(button);
        frame.setVisible(true);
    }

    private JFrame createFrame(String title) {
        JFrame frame = new JFrame(title);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setSize(defaultSize);
        frame.setLocationRelativeTo(null);
        return frame;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new Test().run());
    }
}
 
K

kneitzel

Gast
Was ist das denn für eine dumme Antwort? Da hat jemand das Prinzip von AWT noch nicht verstanden.... traurig.

Wenn Du Deine Aussage etwas ausführen könntest anstatt nur so rum zu poltern.

Wenn die Ersteller der Meinung gewesen wären, dass repaint generell nicht überschrieben werden sollte, dann wäre die Methode wohl final.

Wenn an der Funktionalität von Repaint eine Änderung notwendig wäre: Warum ist es aus Deiner Sicht nicht legitim, dies zu überschreiben?
(Außer natürlich, dass Du dieser Meinung bist und Du natürlich unfehlbar bist .... Aber ich denke mal eher, dass Du irgendwelche Texte einfach nicht richtig verstanden hast wie so oft... repaint wird nicht überschrieben, um irgendwelche Controls zu malen. Evtl. willst Du schlicht auf sowas hinaus.... aber das ist auch nicht gemacht worden, sondern es ging um reine repaint Funktionalitäten ...)
 

mihe7

Top Contributor
Danke an alle, ich merke mir: Timer > Thread.sleep(long), danke
Achtung: es gibt zwei Timer-Klassen (java.util.Timer und javax.swing.Timer). Der hier verwendete Swing-Timer ist halt eine Möglichkeit, um in mehr oder weniger regelmäßigen Abständen Code im EDT auszuführen. Der Code selbst läuft also nicht nebenher, so dass das UI blockiert, so lange animate() läuft. Wenn Du wirklich Aufgaben von langer Dauer ausführen musst, kannst Du z. B. SwingWorker verwenden oder selbst einen Thread erzeugen.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
N Observer: update ruft nicht repaint auf AWT, Swing, JavaFX & SWT 0
K repaint() ruft paint() nicht auf AWT, Swing, JavaFX & SWT 14
D Repaint Funktioniert nicht AWT, Swing, JavaFX & SWT 2
D JUNG Repaint function does not work AWT, Swing, JavaFX & SWT 2
E repaint Probleme AWT, Swing, JavaFX & SWT 13
G listener repaint() - verschiedene Darstellung AWT, Swing, JavaFX & SWT 24
ExceptionOfExpectation Textdarstellung auf einem Canvas mit Hilfe von repaint(); AWT, Swing, JavaFX & SWT 6
J actionperformed wird nicht aufgerufen/ repaint() AWT, Swing, JavaFX & SWT 6
G Repaint wird nicht durchgeführt AWT, Swing, JavaFX & SWT 8
I Swing Verhindern, dass repaint() kaskadiert AWT, Swing, JavaFX & SWT 6
ms_cikar Update swingUtilities Repaint in der Schleife AWT, Swing, JavaFX & SWT 3
T Swing Probleme mit repaint() bzw. JScrollPane AWT, Swing, JavaFX & SWT 7
N Swing JButtons werden nach repaint() doppelt dargestellt AWT, Swing, JavaFX & SWT 12
K Methode repaint() AWT, Swing, JavaFX & SWT 1
B Swing Wann brauche ich repaint() ? AWT, Swing, JavaFX & SWT 1
javampir Swing repaint in JavaFX Anwendung AWT, Swing, JavaFX & SWT 3
A repaint(); AWT, Swing, JavaFX & SWT 9
J Swing ungewünschter Nebeneffekt bei der repaint() Methode AWT, Swing, JavaFX & SWT 3
A Problem: repaint() - Schleife AWT, Swing, JavaFX & SWT 3
S 2D-Grafik repaint()-Aufruf. Und nichts geschieht. AWT, Swing, JavaFX & SWT 5
Joew0815 JDialog repaint() funktioniert nicht wie gewünscht. AWT, Swing, JavaFX & SWT 2
P JPanel und Repaint AWT, Swing, JavaFX & SWT 5
J JavaFX Automatisches Neuzeichnen ("Repaint") abstellen. AWT, Swing, JavaFX & SWT 10
F JTable Repaint Issue AWT, Swing, JavaFX & SWT 1
C Repaint() funktioniert nicht in TabbedPanel AWT, Swing, JavaFX & SWT 5
S JList repaint AWT, Swing, JavaFX & SWT 1
L NullpointerException und Probleme mit repaint() AWT, Swing, JavaFX & SWT 11
M Repaint mittels Button richtig aufrufen klappt nicht AWT, Swing, JavaFX & SWT 1
B Repaint auf JFrame, JLabel und ImageIcon AWT, Swing, JavaFX & SWT 4
K 2D-Grafik Paint - Wie binde ich repaint ein? AWT, Swing, JavaFX & SWT 8
D repaint() klappt anders als vorgestellt AWT, Swing, JavaFX & SWT 15
R Repaint() in Schleifen, Threads AWT, Swing, JavaFX & SWT 13
B Swing Repaint Problem - mal wieder AWT, Swing, JavaFX & SWT 5
P 2D-Grafik Gezielter Repaint einzelner Frames in Java-Game AWT, Swing, JavaFX & SWT 6
javampir Bei repaint nix los AWT, Swing, JavaFX & SWT 2
B Swing repaint() AWT, Swing, JavaFX & SWT 3
Ernesto95 AnimationLoop - Problem bei Aufruf von repaint AWT, Swing, JavaFX & SWT 6
P 2D-Grafik repaint(); steigender RAM Verbauch AWT, Swing, JavaFX & SWT 6
Y KeyListener, GUI Thread, repaint AWT, Swing, JavaFX & SWT 7
S Applet Repaint AWT, Swing, JavaFX & SWT 3
M Programm hängt sich auf nachdem repaint() benutzt wurde AWT, Swing, JavaFX & SWT 2
R Swing Grafikfehler bei repaint AWT, Swing, JavaFX & SWT 2
N repaint() blockieren AWT, Swing, JavaFX & SWT 6
K canvas zeig nach repaint nichts an AWT, Swing, JavaFX & SWT 8
M Repaint() AWT, Swing, JavaFX & SWT 14
J Swing repaint, repaint, repaint AWT, Swing, JavaFX & SWT 8
M Applet repaint() verlangsamen AWT, Swing, JavaFX & SWT 7
R paintComponent malt bei repaint() Rahmen um Panel AWT, Swing, JavaFX & SWT 7
P EDT Problem? Kein Aufruf der repaint Methode AWT, Swing, JavaFX & SWT 6
V Applet JApplet Flackern durch Repaint AWT, Swing, JavaFX & SWT 11
kodela Problem mit repaint() AWT, Swing, JavaFX & SWT 3
N Swing Funktion repaint() updated nicht AWT, Swing, JavaFX & SWT 5
F repaint reagiert nicht AWT, Swing, JavaFX & SWT 8
S AWT Probleme mit repaint() AWT, Swing, JavaFX & SWT 2
D Repaint()? Oder was??? AWT, Swing, JavaFX & SWT 5
M Eine nicht korrekte Darstellung bei repaint() warum? AWT, Swing, JavaFX & SWT 4
T 2D-Grafik Kreis "von Hand" zeichnen -> jedesmal repaint()? AWT, Swing, JavaFX & SWT 6
R validate(), repaint funktionieren nicht! AWT, Swing, JavaFX & SWT 7
B AWT Canvas überdeckt nach repaint() JComboBox-Optionen AWT, Swing, JavaFX & SWT 2
B Swing verschachteltes GUI: repaint() ändert mehr als nur gewünschte Component AWT, Swing, JavaFX & SWT 4
S validate(), invalidate(), repaint(),... Was kommt wann? AWT, Swing, JavaFX & SWT 5
M 2D-Grafik repaint() löscht altes Bild nicht AWT, Swing, JavaFX & SWT 2
J repaint() nicht richtig? AWT, Swing, JavaFX & SWT 6
R repaint erzwingen AWT, Swing, JavaFX & SWT 3
Zettelkasten repaint() von anderen Klassen aufrufen AWT, Swing, JavaFX & SWT 4
H repaint()-Problem - 50% CPU-Auslastung AWT, Swing, JavaFX & SWT 4
P repaint während Thread läuft AWT, Swing, JavaFX & SWT 9
D Repaint Frage, Design Frage AWT, Swing, JavaFX & SWT 2
N Swing MainWindow(JFrame) aktualisieren(neuzeichnen) repaint AWT, Swing, JavaFX & SWT 4
T repaint() Problem AWT, Swing, JavaFX & SWT 2
A 2D-Grafik Repaint - Alternative? AWT, Swing, JavaFX & SWT 3
C JLabel, JTextArea, JScrollPane. repaint(); ? AWT, Swing, JavaFX & SWT 6
N Swing repaint() funktioniert nicht AWT, Swing, JavaFX & SWT 5
T Swing repaint funktioniert nur manchmal? AWT, Swing, JavaFX & SWT 6
K Jpanel repaint problem (Fullscreen) AWT, Swing, JavaFX & SWT 5
V Swing Bei repaint() tut sich nichts AWT, Swing, JavaFX & SWT 7
G ColorReader, bei Fadenkreuz zeichnen mit repaint() flackern AWT, Swing, JavaFX & SWT 19
I Canvas Repaint Probleme AWT, Swing, JavaFX & SWT 2
D Swing Actionlistener verhindert repaint?! AWT, Swing, JavaFX & SWT 2
S JLabel repaint AWT, Swing, JavaFX & SWT 8
C Swing Linux mag mein Swing-repaint() nicht... AWT, Swing, JavaFX & SWT 7
J Swing paintComponent() - repaint() - BufferedImage anzeigen AWT, Swing, JavaFX & SWT 5
Luk10 repaint() auch in anderen Klassen! AWT, Swing, JavaFX & SWT 6
A repaint() zu langsam, bitte um alternativen AWT, Swing, JavaFX & SWT 5
T Überlappende Transparenz und repaint() AWT, Swing, JavaFX & SWT 10
E EINFACHE Verständnisfrage zu repaint(), paintComponent(), usw. AWT, Swing, JavaFX & SWT 16
O Girdbag Formatierung nach repaint verloren AWT, Swing, JavaFX & SWT 2
E Swing - repaint() AWT, Swing, JavaFX & SWT 6
T Image wird nicht angezeigt?! - MediaTracker/repaint AWT, Swing, JavaFX & SWT 9
E AWT Problem mit Repaint (in Loop oder Timer) AWT, Swing, JavaFX & SWT 3
O Exception bei repaint AWT, Swing, JavaFX & SWT 3
D Fragen zu Swing, paintComponent() und repaint AWT, Swing, JavaFX & SWT 6
Dit_ Zeilenmarkierung verschwindet nach repaint() AWT, Swing, JavaFX & SWT 12
A Swing Infinite repaint loop unterbrechen AWT, Swing, JavaFX & SWT 7
hdi Swing EDT macht kein repaint() AWT, Swing, JavaFX & SWT 2
F "Verrutschen" von Komponenten bei repaint() AWT, Swing, JavaFX & SWT 9
Junker Fensterinhalt vor ausführen von repaint komplett löschen. AWT, Swing, JavaFX & SWT 2
T Fenster wird trotz repaint() und revalidate() nicht sofort neu gezeichnet AWT, Swing, JavaFX & SWT 6
E Graphics2D: altes Objekt löschen, wenn repaint aufgerufen wird AWT, Swing, JavaFX & SWT 7
J Swing Verständnis-Problem repaint(int x,int y,int width,int height) AWT, Swing, JavaFX & SWT 3

Ähnliche Java Themen

Neue Themen


Oben