Fragen zu Swing, paintComponent() und repaint

Status
Nicht offen für weitere Antworten.

demian

Mitglied
Hallo liebes Forum,

ich arbeite mich derzeit in Swing und AWT ein und mir sind zwei Dinge grundsätzlich unklar. Es wäre super, wenn mir jemand helfen könnte und die Unklarheiten beseitigen könnte. Anbei ein Codeschnipsel aus dem Buch "Handbuch der Java Programmierung" (Listing3409), das ich deutlich reduziert und auf Swing umgestellt (JFrame statt Frame) habe. Ich hoffe, ihr verzeiht mir, dass das hier sicher nicht als Minimalbeispiel durchgeht, aber ich kann so am besten mein Problem erklären.

[Java] package code;
/*basiert auf Listing3409.java aus Handbuch der Java-Programmierung */
import java.awt.*;
import java.util.*;
import javax.swing.JFrame;

public class Minimalbeispiel
extends JFrame
implements Runnable
{
//Konstanten
private static final int SLEEP = 200;

//Instanzvariablen
private Thread th;
private Vector snake;
protected int dx;
protected int dy;

public static void main(String[] args)
{
Minimalbeispiel frame = new Minimalbeispiel();
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
frame.setSize(d);
frame.setVisible(true);
frame.startAnimation();

}

public Minimalbeispiel()
{
super("Animierte Schlange");
setBackground(Color.LIGHT_GRAY);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
snake = new Vector();
}

public void startAnimation()
{
th = new Thread(this);
th.start();
}

public void run()
{
//Schlange konstruieren
Rectangle cr;
int x = 100;
int y = 100;
for (int i=0; i < 5; ++i) {
cr = new Rectangle(x, y, 20, 20);
x += 20;
snake.addElement(cr);
}

//Vorzugsrichtung festlegen
dx = 1;
dy = 0;

//Schlange laufen lassen
while (true) {
try {
Thread.sleep(SLEEP);
} catch (InterruptedException e){
//nichts
}
moveSnake();
//Was macht hier repaint()? Scheinbar nicht alles neu zeichnen, was passiert, wenn ich die Fenstergröße ändere
repaint();
}
}

public void moveSnake()
{
Dimension size = getSize();
int sizex = size.width-getInsets().left-getInsets().right;
int sizey = size.height-getInsets().top-getInsets().bottom;
Rectangle cr = (Rectangle)snake.firstElement();
int xalt, yalt;
int xtmp, ytmp;

xalt = cr.x + 20 * dx;
yalt = cr.y + 20 * dy;
//Rest der Schlange hinterherziehen
Enumeration e = snake.elements();
while (e.hasMoreElements()) {
cr = (Rectangle)e.nextElement();
xtmp = cr.x;
ytmp = cr.y;
cr.x = xalt;
cr.y = yalt;
xalt = xtmp;
yalt = ytmp;
}
}
//public void paintComponent(Graphics g) funktioniert nicht
public void paint(Graphics g)
{
Rectangle cr;
Enumeration e = snake.elements();
while (e.hasMoreElements()) {
cr = (Rectangle)e.nextElement();
g.setColor(Color.black);
g.fillRect(cr.x,cr.y,cr.width,cr.height);
}
}

}[/Java]

Wenn ihr das Beispiel kompiliert, sollte sich eine Schlange von links nach rechts auf den Weg machen. Zwei Verständnisfragen nun: Wenn man die Fenstergröße ändert, wird die Schlange auf ihre ursprüngliche Größe reduziert, ansonsten wächst sie. Ich kann mir das nur so erklären: Fenster ändert sich ==> System-triggered Event ==> Paint() wird aufgerufen ==> Schlange wird neu gezeichnet und Schlange ist nunmal nur 5 Rechtecke groß. Tut man nichts, wächst die Schlange für den Betrachter einfach deshalb, weil die alten Rechtecke nicht gelöscht werden.

Falls ich das aber richtig verstehe, was macht dann repaint in der run-Methode (Zeile 69) ? Sollte repaint() nicht auch paint aufrufen und damit die Schlange neu zeichnen (damit ich eben eine immer gleich große Schlange und keine wachsende habe).

Meine zweite Frage bezieht sich auf paint(): Dieser Link von Sun (Painting in AWT and Swing) empfiehlt, nie paint zu überschreiben, stattdessen nur paintComponent(). Das klingt dort so, als ob es immer vollkommen ausreichend sei, nur paintComponent zu überschreiben. Mache ich das aber hier (Zeile 97), tut sich einfach nichts. Warum? Wo liegt mein Denkfehler?

Verzeiht die langen Ausführungen zu später Stunde. Trotzdem hoffe ich auf Eure Hilfe.

Grüße Christoph
 

Marco13

Top Contributor
Verzeih' meine kurze Aufwührung wegen der späten Stunde :D : Ein JFrame hat kein paintComponent - dass diese Methode nicht einfach aufgerufen wird, wenn du sie dort einbaust, ist klar. Man sollte aber auch die paint-Methode eines JFrames nicht überschreiben. Wenn man selbst etwas zeichnen will, sollte man von JPanel erben, dort paintComponent überschreiben (und die erste Zeile sollte dort [c]super.paintComponent(g);[/c] sein, und dieses Panel dann in's ContentPane vom JFrame legen.
Und noch ganz kurz: "repaint" ruft nicht "paint" auf. "repaint" ist nur ein "Anstoßen" - ein Hinweis nach dem Motto: "Zeichne mal so bald wie möglich neu".
 

javimka

Top Contributor
Es ist durchaus legitim auch das paint zu überschreiben, wenn das Sinn macht. Z.B. wenn mann die gesamte Komponente transparent zeichnen möchte, kann man das machen. Meistens ist das aber unnötig und man überschreibt deshalb paintComponent. Der Grund, paintComponent() zeichnet den Inhalt einer Komponente. paint() ruft der Reihe nach paintComponent(), paintBorder() und paintChildren auf. Überschreibt man dies unvorsichtig, werden keine Border und keine Kinderkomponenten mehr gezeichnet.
 

Marco13

Top Contributor
Ja, das stimmt (so viel zum Thema Fragestellerspezifische Antworten :bae: ), zumindest für Components wie das JPanel, aber bei einem JFrame paint zu überschreiben ist schon ein bißchen "heikel"... man sollte sich zumindest mal ansehen, was DER in der paint so alles macht...
 

André Uhres

Top Contributor
Versuch's mal so:
Java:
import java.awt.*;
import java.util.*;
import javax.swing.*;

public class Minimalbeispiel extends JFrame implements Runnable {

    private static final int SLEEP = 200;
    private Thread th;
    private Vector snake;
    protected int dx;
    protected int dy;
    private final MyPanel myPanel;

    public Minimalbeispiel() {
        super("Animierte Schlange");
        setBackground(Color.LIGHT_GRAY);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        snake = new Vector();
        setSize(600, 300);
        setLocationRelativeTo(null);
        myPanel = new MyPanel(snake);
        add(myPanel);
        startAnimation();
    }

    public void startAnimation() {
        th = new Thread(this);
        th.start();
    }

    public void run() {
        //Schlange konstruieren
        Rectangle cr;
        int x = 100;
        int y = 100;
        for (int i = 0; i < 5; ++i) {
            cr = new Rectangle(x, y, 20, 20);
            x += 20;
            snake.addElement(cr);
        }
        //Vorzugsrichtung festlegen
        dx = 1;
        dy = 0;
        //Schlange laufen lassen
        while (true) {
            try {
                Thread.sleep(SLEEP);
            } catch (InterruptedException e) {
                //nichts
            }
            moveSnake();
        }
    }

    public void moveSnake() {
        Rectangle cr = (Rectangle) snake.firstElement();
        int xalt, yalt;
        int xtmp, ytmp;
        xalt = cr.x + 20 * dx;
        yalt = cr.y + 20 * dy;
        //Rest der Schlange hinterherziehen
        Enumeration e = snake.elements();
        while (e.hasMoreElements()) {
            if (xalt > myPanel.getWidth()) {
                dx = -1;
            } else if (xalt < 0) {
                dx = 1;
            }
            cr = (Rectangle) e.nextElement();
            xtmp = cr.x;
            ytmp = cr.y;
            //
            int OFFSET = 20;
            myPanel.repaint(cr.x - OFFSET, cr.y - OFFSET,
                    cr.width + OFFSET * 2, cr.height + OFFSET * 2);
            cr.x = xalt;
            cr.y = yalt;
            myPanel.repaint(cr.x - OFFSET, cr.y - OFFSET,
                    cr.width + OFFSET * 2, cr.height + OFFSET * 2);
            //
            xalt = xtmp;
            yalt = ytmp;
        }
    }

    public static void main(String[] args) {
        Runnable gui = new Runnable() {

            public void run() {
                new Minimalbeispiel().setVisible(true);
            }
        };
        SwingUtilities.invokeLater(gui);

    }
}

class MyPanel extends JPanel {

    private final Vector snake;

    MyPanel(Vector snake) {
        this.snake = snake;

    }

    @Override
    protected void paintComponent(final Graphics g) {
        super.paintComponent(g);
        Rectangle cr;
        Enumeration e = snake.elements();
        while (e.hasMoreElements()) {
            cr = (Rectangle) e.nextElement();
            g.setColor(Color.black);
            g.fillRect(cr.x, cr.y, cr.width, cr.height);
        }
    }
}
Siehe auch:
Malen in Swing Teil 1: der grundlegende Mechanismus - Byte-Welt Wiki
Lesson: Performing Custom Painting (The Java™ Tutorials > Creating a GUI With JFC/Swing)
Tipp: wenn du eine Methode überschreiben willst, benutze die @Override Annotation, dann sagt der Compiler dir Bescheid, falls die Methode in deiner Klasse nicht überschrieben/implementiert werden kann.
 
Zuletzt bearbeitet:

demian

Mitglied
Hallo Zusammen,

erstmal vielen Dank für Eure Hilfe. Jetzt ist mir wieder alles klar: Ich habe ja in dem Swing-Tutorial von Sun gelesen, dass JFrame ein Container und keine JComponent ist. Wahrscheinlich macht deswegen dort paintComponent() keinen Sinn. Sehr gut nun zu wissen, da grundsätzlich noch ein JPanel darüber zu legen und das zum JFrame hinzuzufügen.

Und André, vielen Dank für dein angepasstes Beispiel. Es arbeitet jetzt so, wie ich es anfangs wollte, und ich kann es nun am Code nachvollziehen. Super! Ich werde mir auch gleich deine Links durchlesen.

Schönen Abend Euch noch.

Grüße Christoph
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
U Zwei Fragen zu eienr Swing Aufgabe AWT, Swing, JavaFX & SWT 2
B Zeichnen in Swing - Jede Menge Fragen! AWT, Swing, JavaFX & SWT 2
C Mehrer Fragen zu großem kompletten Swing Beispiel AWT, Swing, JavaFX & SWT 5
G performance fragen zu AWT, Swing AWT, Swing, JavaFX & SWT 14
thor_norsk Allgemeine Fragen AWT, Swing, JavaFX & SWT 6
thor_norsk Allgemeine Fragen AWT, Swing, JavaFX & SWT 4
K JavaFX Allgemeine Fragen zu dem Aufbau eines Programms hinsichtlich der Klassen AWT, Swing, JavaFX & SWT 1
D Fragen zur GUI AWT, Swing, JavaFX & SWT 4
M NetBeans JFrame Grundlangen fragen AWT, Swing, JavaFX & SWT 6
T JavaFX Allgemeine Fragen zu JavaFX (uA zu Properties) AWT, Swing, JavaFX & SWT 6
D Panel wird nicht angezeigt und Fragen zum CardLayout AWT, Swing, JavaFX & SWT 6
K Fragen zu JavaFx Canvas AWT, Swing, JavaFX & SWT 0
N Swing Fragen zu non-modal JDialog AWT, Swing, JavaFX & SWT 1
Q Fragen zur JMenuBar & Co. AWT, Swing, JavaFX & SWT 3
F DefaultTreeCellEditor - Fragen zur Groesse und zum Icon beim Editieren AWT, Swing, JavaFX & SWT 4
Kenan89 JMenu Fragen AWT, Swing, JavaFX & SWT 5
Luk10 (LWJGL) Fragen zu VBOs AWT, Swing, JavaFX & SWT 21
M Swing JTextPane + Scrollbar = Fragen AWT, Swing, JavaFX & SWT 15
S Fragen zu JList AWT, Swing, JavaFX & SWT 3
J Das erste Projekt und ein Haufen von Fragen. Der SudokuReader. AWT, Swing, JavaFX & SWT 4
Luk10 Fragen zum Laden von Fonts AWT, Swing, JavaFX & SWT 4
Luk10 Fragen zum Koordinaten System AWT, Swing, JavaFX & SWT 3
M JTable Grundlegende Fragen AWT, Swing, JavaFX & SWT 4
B Prozentrechner GUI Fragen AWT, Swing, JavaFX & SWT 4
H Fragen zu JPanel und JButton AWT, Swing, JavaFX & SWT 3
Q Swing Zeichenprogramm, grundlegende Fragen AWT, Swing, JavaFX & SWT 8
U Swing Fragen bezüglich Multithreaded GUIs (Grundlagen): AWT, Swing, JavaFX & SWT 3
R LayoutManager GridBagLayout Fragen AWT, Swing, JavaFX & SWT 10
A diverse Layout-Fragen AWT, Swing, JavaFX & SWT 4
M LayoutManager Einige Fragen zum GridBagLayout AWT, Swing, JavaFX & SWT 13
H Swing Zwei Fragen AWT, Swing, JavaFX & SWT 5
S 2D-Grafik Diverse Fragen zu Imagemanipulation in Java AWT, Swing, JavaFX & SWT 11
C Swing Grundsätzliche Fragen zu MVC AWT, Swing, JavaFX & SWT 8
F 3 Fragen zu Applets AWT, Swing, JavaFX & SWT 4
L Klick auf JTable -> EditorPane manipulieren, Fragen zu TableModel AWT, Swing, JavaFX & SWT 9
S Fragen zu GridBagLayout AWT, Swing, JavaFX & SWT 6
D GridBagLayout und JEditorPane (mehrere fragen) AWT, Swing, JavaFX & SWT 2
A Swing einfache fragen zu frame AWT, Swing, JavaFX & SWT 10
P Mehrere Fragen AWT, Swing, JavaFX & SWT 4
A Fragen zu Microber AWT, Swing, JavaFX & SWT 4
T Fragen zu JList und DnD AWT, Swing, JavaFX & SWT 13
I Einige Fragen zu JList AWT, Swing, JavaFX & SWT 6
I Drei Fragen/Probleme mit einer JTable AWT, Swing, JavaFX & SWT 9
G Fragen zum FileChooser AWT, Swing, JavaFX & SWT 5
M 2 Kleine Fragen zum JOptionFrame AWT, Swing, JavaFX & SWT 5
J Fragen zu JTable und JScrollpane AWT, Swing, JavaFX & SWT 2
R Frage zu Listfeld oder jTable, auch andere Fragen AWT, Swing, JavaFX & SWT 5
C Fragen zur Darstellung einer JTable mittels Renderer AWT, Swing, JavaFX & SWT 2
ModellbahnerTT Fragen zu AWT AWT, Swing, JavaFX & SWT 3
S Fragen Databinding? AWT, Swing, JavaFX & SWT 3
J Fragen zu AWT Komponenten AWT, Swing, JavaFX & SWT 5
U 2 Fragen zu BufferedImages AWT, Swing, JavaFX & SWT 19
J Fragen zur Vererbung und Update AWT, Swing, JavaFX & SWT 12
J Fragen zum SyntaxHighlighting (DefaultStyledDocument) AWT, Swing, JavaFX & SWT 2
I Ein paar SWT Fragen AWT, Swing, JavaFX & SWT 10
P Zwei Fragen zu Bildern in Applets AWT, Swing, JavaFX & SWT 2
isowiz Einige Fragen zur ersten eigenen Sing-Applikation AWT, Swing, JavaFX & SWT 4
G 2 Fragen JDesktopPane AWT, Swing, JavaFX & SWT 4
S Fragen zu einem Beispiel(Swings und AWT) AWT, Swing, JavaFX & SWT 33
G Fragen zum Ocean Look and Feel AWT, Swing, JavaFX & SWT 3
G Neue Komponente erstellen - Fragen/Probleme mit MouseEvents AWT, Swing, JavaFX & SWT 2
Y 2 Fragen- JList Inhalt ändern und Fenster invisible setzen AWT, Swing, JavaFX & SWT 5
C Gemischte Fragen AWT, Swing, JavaFX & SWT 10
G Fragen zu JList AWT, Swing, JavaFX & SWT 12
K 2 fragen:JCheckBoxMenuItem und ComboBox AWT, Swing, JavaFX & SWT 2
T Mehrere Fragen zu JToolBar AWT, Swing, JavaFX & SWT 2
N 2 Fragen (zu binärem Suchen und Scrollbar) AWT, Swing, JavaFX & SWT 6
B Einige Fragen zum GUI AWT, Swing, JavaFX & SWT 3
Juelin javax.swing in javafx AWT, Swing, JavaFX & SWT 1
A Eclipse 2023 und Swing AWT, Swing, JavaFX & SWT 4
W 2 JTables in einem Swing-Fenster? AWT, Swing, JavaFX & SWT 5
H Swing Componente zur Läufzeit ändern AWT, Swing, JavaFX & SWT 3
B Actionlistener mit Java Swing AWT, Swing, JavaFX & SWT 2
W Gibt es einen "automatischen Listener" in Swing oder JTable oder der ATM-Klasse? AWT, Swing, JavaFX & SWT 14
H Swing Buttons erst nach Klick sichtbar AWT, Swing, JavaFX & SWT 13
ExceptionOfExpectation Anpassung von JKomponentengrößen (Swing) AWT, Swing, JavaFX & SWT 3
thor_norsk AWT SWING Aufgabe AWT, Swing, JavaFX & SWT 7
M Swing Bilder in Swing anzeigen AWT, Swing, JavaFX & SWT 9
H Swing , GridLayout, Größenbestimmung der Komponenten im Layout AWT, Swing, JavaFX & SWT 8
H Simple Animation mit Swing AWT, Swing, JavaFX & SWT 2
Guybrush Threepwood Einfachste Möglichkeit zum Abspielen eines Videos in Swing AWT, Swing, JavaFX & SWT 4
A Swing ProgressBar über 2 parallel laufende Threads AWT, Swing, JavaFX & SWT 2
M Swing GridLayout AWT, Swing, JavaFX & SWT 2
O return-Statement mit Swing AWT, Swing, JavaFX & SWT 6
O Ein Java-Programm mit Swing steuern AWT, Swing, JavaFX & SWT 1
Monokuma Swing zu JavaFX AWT, Swing, JavaFX & SWT 5
J Swing Slider AWT, Swing, JavaFX & SWT 11
G Thread starten Swing AWT, Swing, JavaFX & SWT 5
G Swing JPasswordField AWT, Swing, JavaFX & SWT 12
L Swing Button Farbe ändern/wechseln AWT, Swing, JavaFX & SWT 2
C Swing AWT GUI Anfänger Aufgabe AWT, Swing, JavaFX & SWT 7
W Inject bei einem Swing Frontend AWT, Swing, JavaFX & SWT 8
L Kommunikation zwischen Klassen / Konstruktoren bei Swing AWT, Swing, JavaFX & SWT 9
M Feldvalidierung swing AWT, Swing, JavaFX & SWT 4
E Swing Componenten werden nach Änderung des display modes verzerrt dargestellt AWT, Swing, JavaFX & SWT 8
D [Swing] Anordnung von Komponenten mit GridLayout Manager AWT, Swing, JavaFX & SWT 13
O Zukunft von Swing und JavaFX ? AWT, Swing, JavaFX & SWT 3
S Swing Fenster State Machine AWT, Swing, JavaFX & SWT 1
T Swing Swing an Bildschirm anpassen AWT, Swing, JavaFX & SWT 3
S Swing Panel wird nicht neu gezeichnet AWT, Swing, JavaFX & SWT 3

Ähnliche Java Themen

Neue Themen


Oben