swing und repaint-Ersatz

Status
Nicht offen für weitere Antworten.

Antoras

Top Contributor
Hallo,

ich hab schon des öfteren auf awt-Oberflächen Grafiken dargestellt - wenn ich diese dann z.B per Mausklick an einen anderen Ort verschoben habe, dann wurde das Schlüsselwort repaint benötigt, da sonst die alte Grafik nicht mehr gelöscht wurde.

Ich hab selbiges jedoch noch nie auf swing-Oberfläche hinbekommen. Das Problem ist, dass die alte Grafik - trotz repaint-Befehls - nicht verschwindet, meine Oberfläche wird schlichtweg nicht neu gezeichnet. Ich bin schon auf validate gestoßen, das hat jedoch nicht funktioniert. Ich bin daraus aber auch nicht so richtig schlau geworden. validate soll glaub nur Layouts neu skalieren.

Ist validate hier der falsche Ansatz? Wäre schön, wenn mir hier jemand weiterhelfen könnte.
 

André Uhres

Top Contributor
Normal zeichnen wir auf ein JPanel. Dort überschreiben wir "protected void paintComponent(Graphics g)":
Code:
   @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawRect(...);//hier zeichnen wir was wir wollen
        ...
    }
Zum Verschieben hängen wir einen MouseListener und MouseMotionListener an das JPanel.
Das Neuzeichnen besorgt die Methode repaint, die wir auf dem JPanel aufrufen.
"validate" hat eigentlich in diesem Kontext nix zu suchen :wink:

Die multi-arg Version von repaint erlaubt uns, das Cliprechteck der Komponente
zu schrumpfen (der Bereich des Bildschirmes, der durch den Malvorgang beeinflusst wird),
damit der Malvorgang leistungsfähiger werden kann. Wir verwenden diese Technik,
um zu vermeiden, Abschnitte des Bildschirmes neu zu malen,
die nicht geändert haben. Die keine-arg Version dieser Methode
malt immer die gesamt Fläche der Komponente neu.

Wenn wir das Cliprechteck schrumpfen, rufen wir repaint nicht einmal,
sondern zweimal auf. Der erste Aufruf malt den Bereich der Komponente neu,
in dem die bewegte Figur vorher war (das ererbte Verhalten ist, den Bereich mit der
gegenwärtigen Hintergrundfarbe zu füllen.). Der zweite Aufruf malt den Bereich
der Komponente neu, in dem die Figur zur Zeit ist.

Wir können repaint innerhalb des gleichen Eventhandlers mehrfach aufrufen, aber
Swing nimmt diese Informationen und malt die Komponente in einem einzigen Vorgang neu.
 

Antoras

Top Contributor
Tut mir leid für die späte Antwort, bin in den letzten Tagen aber nicht zum Programmieren gekommen.

Also, das mit dem paintComponent hab ich jetzt nicht richtig verstanden. Wie genau setze ich das ein? Muss ich von der Methode aus meine anderen aufrufen?

Und dieses multi-arg repaint erstellt also nur die veränderten Bereiche neu? Dafür muss ich repaint also nur zweimal in dieser paintComponent-Methode aufrufen?
 

Luca_94

Mitglied
So, bin zwar auch noch Anfänger, denke aber das war so gemeint:

Code:
public class TestFrame extends JFrame{
/** Überschreiben von paintComponent */
protected void paintComponent(Graphics g){
super.repaint(); //ruft die repaint() Methode der Superklasse auf (Füllen des "alten Bildes" mit der Hintergrundfarbe)

//anderen lustigen Malcode schreiben

}}

Hoffe es hilft dir weiter,

Gruß Luca
 

hdi

Top Contributor
Nein, du machst dir ein JPanel und überschreibst seine paintComponent(Graphics g) Methode, da hat auch
repaint() nix drin zu suchen!

zB:

Code:
JPanel p = new JPanel(){
     @Override
     protected void paintComponent(Graphics g){
            super.paintComponent(g) // löscht alles was darauf gemalt wurde
            // hier sagst du dann, was gemalt werden soll, zB ein Rechteck:
            // g.drawRect(...);
     }
}

So, jetz kannste einen MouseListener an das Panel hängen per

Code:
p.addMouseListener(new MouseListener(){
            ....
});

und innerhalb der mouse-methoden veränderst du zB die position des rechtecks, das ja vom Panel gemalt
wird.

Um den Malvorgang zu starten, rufst du wie gewohnt die repaint() Methode auf dem Panel auf, denn
diese wiederum ruft die paintcomponent Methode auf, die du ja überschrieben hast:

Code:
p.repaint();

Das is übrigens nur eine "Bitte" an das Panel, dass es sich doch bei Gelegenheit neu malen sollte. Heisst nicht
unbedingt, dass es das tut. Tut es aber in den meisten Fällen doch, zumindest wenn du nicht alle paar ms die
Methode abfeuerst (so ein Arschloch ist das Panel dann auch wieder nicht ;) Frag mich nicht, wieso das genau so is,
das is für mich zu kompliziert, da können dir die Profis mehr erzählen)

Das wäre jetz also diese "nicht-arg" Variante, in der alles immer neu gemalt wird (weil du durch den ersten
Befehl in der Methode ja alles löscht). Solange du nicht ewig viel zu zeichnen hast, kannste das auch so lassen.
Der Vorgang geht halt schneller, wenn er nicht alles neumalen muss immer, aber das spielt nur bei komplexen
Zeichen-Vorgängen ne Rolle und muss bei simplen Zeichen-Vorgängen nicht beachtet werden (ausser du bist ein Performance Fetischist)
 

Luca_94

Mitglied
*Beißt in die Tastatur*

Verdammt, stimmt, des war mit super.paintComponent

Sorry Antoras, hab da was durcheinandergebracht :?

Gruß Luca
 

Antoras

Top Contributor
Muss man zwingend auf ein JPanel zeichnen?

Und das mit dem MouseListener funktioniert noch nicht so richtig. Irgendwie will sich mein Kreis nicht bewegen.

Mainklasse:
Code:
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;


public class Test extends JFrame {	
	
	private Kreis kreis;
	
	public static void main(String[] args) {
		new Test(300, 300);
	}
	
	public Test(int w, int h) {
		setPreferredSize(new Dimension(w, h));
		setDefaultCloseOperation(EXIT_ON_CLOSE);	
		setLocation(400, 400);
		pack();
		GUI();
		setVisible(true);
	}
	
	public void GUI() {
//		setLayout(new FlowLayout());
		
		JPanel p = new JPanel() {
			protected void paintComponent(Graphics g) {
				super.paintComponents(g);
				kreis = new Kreis(100, 100, 100, 100);
				kreis.malen(g);
			}
		};
		p.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				bewegen(e);
			}
		});
		getContentPane().add(p);
		p.repaint();		
	}
	
	
	protected void bewegen(MouseEvent e) {
		int x = e.getX();
		int y = e.getY();
		kreis.gehen(x, y);
		
		
	}
}
Klasse Kreis:
Code:
import java.awt.Graphics;


public class Kreis {
	
	private int xPos;
	private int yPos;
	private int durchM;
	private int schrittweite;
	
	public Kreis(int x, int y, int d, int s) {
		xPos = x;
		yPos = y;
		durchM = d;
		schrittweite = s;
	}
	
	public void malen(Graphics g) {
			g.drawOval(xPos, yPos, durchM, durchM);		
	}
	
	public void gehen(int x, int y) {
		if(xPos < x) xPos = xPos+schrittweite;
		if(xPos > x) xPos = xPos-schrittweite;
		if(yPos < x) yPos = yPos+schrittweite;
		if(yPos > x) yPos = yPos-schrittweite;
	}

}

Ich aktualisiere mein JPanel nicht alle paar Millisekunden, von dem her kann es mir egal sein ob repaint immer geht. Haupsache es geht dann wenn ich klicke - "Millisekundenschnell" kann ich gar nicht klicken ;)
 

André Uhres

Top Contributor
In Swing malen wir in der Regel auf JComponent, oder auf eine von JComponent
abgeleitete Komponente (wie z.B. JPanel).
Bei den Hauptfehlern im vorgeschlagenen Code geht es darum,
wann man den Kreis erzeugt und wann man repaint() aufruft.
Den Kreis dürfen wir selbstverständlich nicht immer wieder, sondern nur am Anfang erzeugen.
"repaint" müssen wir beim Bewegen aufrufen.
Die folgende Lösung benutzt die multi-arg Version von repaint,
die uns erlaubt, das Cliprechteck der Komponente zu schrumpfen,
damit der Malvorgang leistungsfähiger werden kann (siehe dazu auch meinen obigen Beitrag):
Code:
/*
 * KreisBewegen.java
 */
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class KreisBewegen extends JFrame {
    private Kreis kreis; 
    private JPanel panel;
    public KreisBewegen(final int w, final int h) {
        setPreferredSize(new Dimension(w, h));
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLocation(400, 400);
        pack();
        GUI();
    }
    public void GUI() {
        panel = new JPanel() {
            @Override
            protected void paintComponent(final Graphics g) {
                super.paintComponent(g);
                if(kreis == null){
                    kreis = new Kreis(100, 100, 100, 100);
                }
                kreis.malen(g);
            }
        };
        panel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(final MouseEvent e) {
                bewegen(e);
            }
        });
        getContentPane().add(panel);
    }
    protected void bewegen(final MouseEvent e) {
        int x = e.getX();
        int y = e.getY();
        int OFFSET = 1;
        panel.repaint(kreis.getXPos(), kreis.getYPos(), kreis.getDurchM() + OFFSET,
                kreis.getDurchM() + OFFSET);
        kreis.gehen(x, y);
        panel.repaint(kreis.getXPos(), kreis.getYPos(), kreis.getDurchM() + OFFSET,
                kreis.getDurchM() + OFFSET);
    }
    public static void main(final String[] args) {
        Runnable gui = new Runnable() {
            public void run() {
                new KreisBewegen(300, 300).setVisible(true);
            }
        };
        //GUI must start on EventDispatchThread:
        SwingUtilities.invokeLater(gui);
    }
}
class Kreis {
    private int xPos;
    private int yPos;
    private int durchM;
    private int schrittweite;
    public Kreis(final int x, final int y, final int d, final int s) {
        xPos = x;
        yPos = y;
        durchM = d;
        schrittweite = s;
    }
    public void malen(final Graphics g) {
        g.drawOval(xPos, yPos, durchM, durchM);
    }
    public void gehen(final int x, final int y) {
        if (xPos < x) {
            xPos = xPos + schrittweite;
        }
        if (xPos > x) {
            xPos = xPos - schrittweite;
        }
        if (yPos < y) {
            yPos = yPos + schrittweite;
        }
        if (yPos > y) {
            yPos = yPos - schrittweite;
        }
    }
    public int getXPos() {
        return xPos;
    }
    public int getYPos() {
        return yPos;
    }
    public int getDurchM() {
        return durchM;
    }
}
 

Antoras

Top Contributor
Hallo,

danke dir André Uhres, du hast mir sehr weitergeholfen. Jetzt hab ich eigentlich alles verstanden. Hab auch einen aus meiner Klasse gefragt, der schon seit einigen Jahren programmiert und der konnte mir auch weiterhelfen.

Und natürlich auch ein Danke an alle anderen, ihr habt mir auch sehr geholfen.

Den Kreis dürfen wir selbstverständlich nicht immer wieder, sondern nur am Anfang erzeugen.
Stimmt, hab ich nicht drangedacht.

"repaint" müssen wir beim Bewegen aufrufen.
Eigentlich auch ganz logisch.

Nochmals Danke!
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
Antoras Swing repaint und Nullpointer Java Basics - Anfänger-Themen 6
G Automatischer repaint bei Swing so wie bei AWT? Java Basics - Anfänger-Themen 7
J SWING UI Designer und zeichnen Java Basics - Anfänger-Themen 4
G Maven Swing: Wie verwende ich WindowListener ? Java Basics - Anfänger-Themen 2
C Threads und Swing Java Basics - Anfänger-Themen 9
A Swing: Raumshiff Java Basics - Anfänger-Themen 3
U Warum kriege ich hier eine nullpointer exception, sehe den Fehler nicht (swing) Java Basics - Anfänger-Themen 1
nbergmann Wo ist javax.swing.JOptionPane gespeichert? Java Basics - Anfänger-Themen 4
StevenGG Java swing "New Integer" Java Basics - Anfänger-Themen 5
T Java Swing - Dreieck zeichnen mit verschiedenen Variablen Java Basics - Anfänger-Themen 8
O ImageIcon, Swing Java Basics - Anfänger-Themen 1
O Swing JPanel Java Basics - Anfänger-Themen 4
F Swing - Fehler - Paint Methode Java Basics - Anfänger-Themen 7
M Input/Output Java Swing: Prüft ob Text aus JTextField ausschließlich Integer enthält Java Basics - Anfänger-Themen 15
mobaer Swing Timer stoppen Java Basics - Anfänger-Themen 3
M Wie kann ich hier ein Textfeld hinzufügen Java Swing? Java Basics - Anfänger-Themen 1
M SpielMenü mit Swing Java Basics - Anfänger-Themen 3
M Wie kann ich eine Eingabe im Java-Swing übergeben? Java Basics - Anfänger-Themen 1
N javax swing JOptionPane Hilfe Java Basics - Anfänger-Themen 3
H Swing Button hat falsche Größe Java Basics - Anfänger-Themen 5
C Der Swing Layout-Manager hasst mich Java Basics - Anfänger-Themen 4
M Java swing im Browser starten Java Basics - Anfänger-Themen 0
M JavaFX in Swing-Applikationen einbetten Java Basics - Anfänger-Themen 5
Z Threads SWING mit EventQueue.invokeLater Java Basics - Anfänger-Themen 1
P JDK installieren javac behauptet Javax.swing existiert nicht Java Basics - Anfänger-Themen 8
K Ascii Converter mit Swing Java Basics - Anfänger-Themen 4
b1ck Interface Verständnisfrage zum GUI mit "swing" Java Basics - Anfänger-Themen 1
N Erste Schritte Karte in SWING Application Java Basics - Anfänger-Themen 4
D Mehrfacherfassung in Swing GUI Java Basics - Anfänger-Themen 12
D Datum aus Swing in MySQL DB speichern Java Basics - Anfänger-Themen 22
R warum kann System.out.println(..) etwas, was Swing-Elemente Nicht können ? Java Basics - Anfänger-Themen 11
J Input/Output Charset Swing- Eingaben? Java Basics - Anfänger-Themen 8
S JUnit - Swing- Anwendung wird nicht neu gestartet Java Basics - Anfänger-Themen 0
Q Threads Threads in Swing Anwendungen Java Basics - Anfänger-Themen 5
B Swing intstalliert Eclips{}, mackiert Rot Java Basics - Anfänger-Themen 6
U Java Swing Timer mit ButtonKlick starten u. nach 12 Sekunden Befehl ausführen Java Basics - Anfänger-Themen 7
S Input/Output In Java Swing auf Button warten? Java Basics - Anfänger-Themen 9
N Problem mit Swing Textfeld und Zugriff aus anderer Klasse Java Basics - Anfänger-Themen 6
G Performance - höhere Anzahl Swing Elemente Java Basics - Anfänger-Themen 5
B Java Swing "Zeichenfläche" Java Basics - Anfänger-Themen 1
O Alternative zum swing-Timer Java Basics - Anfänger-Themen 5
F Swing Applet: mehrere Komponenten hinzufügen Java Basics - Anfänger-Themen 1
F Platzieren von Komponenten in Swing Applet funktioniert nicht Java Basics - Anfänger-Themen 3
P Hintergrundbild in Swing einfügen Java Basics - Anfänger-Themen 3
C Swing frage Java Basics - Anfänger-Themen 8
T Rechenprogramm mit Swing Java Basics - Anfänger-Themen 3
K Swing Darstellungsproblem Java Basics - Anfänger-Themen 11
G Verständnisproblem mit swing Java Basics - Anfänger-Themen 6
P Swing - Blackscreen Java Basics - Anfänger-Themen 10
Y Random-Objekt und Swing Java Basics - Anfänger-Themen 4
M Klassen Hilfe bei SWING Java Basics - Anfänger-Themen 5
S GUI Problem: Swing Java Basics - Anfänger-Themen 8
M Javax.swing - Timer(2 Button) Java Basics - Anfänger-Themen 17
J Timer - Swing Java Basics - Anfänger-Themen 5
B Erste Schritte Primefaces -> Swing Gui Java Basics - Anfänger-Themen 7
T Swing, SWT oder JavaFX Java Basics - Anfänger-Themen 8
S Programmoberfläche mit Java-Swing - Herangehensweise Java Basics - Anfänger-Themen 20
E Fragen zu paintXXX in Swing Java Basics - Anfänger-Themen 7
D Erste Schritte bash-Befehl mit Swing ausführen Java Basics - Anfänger-Themen 8
A Alternative zum manuellen Swing programmieren?? Java Basics - Anfänger-Themen 4
S Android fuer Swing-Kenner..? Java Basics - Anfänger-Themen 6
J Swing Timer Java Basics - Anfänger-Themen 3
B Seltsamer Fehler in SWING anwendung Java Basics - Anfänger-Themen 2
D GPS Tracker Swing Java Basics - Anfänger-Themen 2
L Erste Schritte Swing oder SWT Paint mit Grafikkarte? Java Basics - Anfänger-Themen 7
B Einstieg in swing GUI Java Basics - Anfänger-Themen 7
S Swing Eingabe Erzwingen Java Basics - Anfänger-Themen 3
S Swing JTable Java Basics - Anfänger-Themen 7
Z Input/Output Programm mit Swing umsetzen Java Basics - Anfänger-Themen 6
K Eclipse wie Swing per Drag und Drop erstellen Java Basics - Anfänger-Themen 2
V Dropdown Button in einer GUI (Java Swing) Java Basics - Anfänger-Themen 12
S Swing, Gridbaglayout Panel in Panel;funzt nicht!! Java Basics - Anfänger-Themen 3
O swing komponenten werden nicht angezeigt Java Basics - Anfänger-Themen 6
S Swing, Panel über Hintergrundbild!! Java Basics - Anfänger-Themen 6
P Im Fenster bleiben (swing) Java Basics - Anfänger-Themen 16
M Einfacher Swing Wizard Java Basics - Anfänger-Themen 3
E Swing FileWrite?? Java Basics - Anfänger-Themen 3
S Umlaute in Swing-GUI Java Basics - Anfänger-Themen 8
K Drop-down Menü (swing) Java Basics - Anfänger-Themen 4
M Timer-Thread in Swing öffnet jedes Mal ein neues Fenster Java Basics - Anfänger-Themen 6
M Swing Klasse auch per Kommandozeile starten? Java Basics - Anfänger-Themen 2
S JAVA Swing Eventlistener Java Basics - Anfänger-Themen 11
P Swing - Welche Klasse für ausgeben von Ergebnissen? Java Basics - Anfänger-Themen 3
V Swing Componenten werden auf Mac nicht angezeigt Java Basics - Anfänger-Themen 19
J Überfordert mit Swing Java Basics - Anfänger-Themen 5
B Baum > Baum-Swing Java Basics - Anfänger-Themen 4
B Bei Swing weg vom North-West-South-East-Prinzip Java Basics - Anfänger-Themen 2
K Swing Fenster jede sec.neuzeichnen Java Basics - Anfänger-Themen 14
F Werteübergabe in Swing Formularen (gui Builder) Java Basics - Anfänger-Themen 9
L Swing GridBagLayout Java Basics - Anfänger-Themen 3
K Bild als Hintergrund in einem Swing Fenster Java Basics - Anfänger-Themen 21
J unterschied zwischen awt und swing Java Basics - Anfänger-Themen 6
C Swing i.V.m. Threads Java Basics - Anfänger-Themen 2
J XML Viewer for Swing Java Basics - Anfänger-Themen 6
Y Anfänger Hausaufgabe... Swing Java Basics - Anfänger-Themen 6
W Zeichnen in Swing Java Basics - Anfänger-Themen 7
B Swing Applikation mit mehreren Klassen Java Basics - Anfänger-Themen 2
C Swing, Buttons Wert zuweisen Java Basics - Anfänger-Themen 3
Luk10 Swing timer und Threads Java Basics - Anfänger-Themen 4
J Java GUI in Swing und das MVC Paradigma Java Basics - Anfänger-Themen 3

Ähnliche Java Themen

Neue Themen


Oben