Swing Generierung mehrerer Kreise per MouseListener

userSeb

Mitglied
Hallo,
ich beschäftige mich seit 3 Tagen mit Java und habe vorher noch nie großartig programmiert. Ich habe mir folgende Aufgabe gestellt: Ich möchte in einem Fenster Kreise generieren an der Stelle, wo ich mit der Maus hinklicke. Es sollen aber alle Kreise erhalten bleiben. Leider verschwindet aber immer der letzte Kreis, sodass nur der aktuelle Klick angezeigt wird. Außerdem funktioniert am Anfang erst der zweite Klick.
Goolge und die Forensuche habe ich bereits bemüht, war aber leider nicht in der Lage, die Lösungsansätze für mich zu übertragen.
Hier mein Code:

Java:
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.*;

public class Main extends JFrame
{
	public static void main(String[] args)
	{	
		new Zeichenfeld();

	}
}	

class Zeichenfeld extends JFrame implements MouseListener
{
	//private int x = 5;
	//private int y = 5;

	public Zeichenfeld()
	{	
		setTitle("Zeichenfeld");
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setLocation(50,50);
		setSize(Toolkit.getDefaultToolkit().getScreenSize().width-100,Toolkit.getDefaultToolkit().getScreenSize().height-100);
		
		setVisible(true);
		addMouseListener(this);
	}
	
    public void zeichnen(Graphics g, int x1, int y1) 
    {
    	int radius=100;
        paintComponents(g);
        g.setColor(new Color(0, 0, 0));
        g.drawOval(x1-(radius/2), y1-(radius/2), radius, radius);
    }

	
	public void mousePressed(MouseEvent e)
	{	
		int x = e.getX();
		int y = e.getY();
		zeichnen(getGraphics(),x,y);	
	}

	public void mouseMoved(MouseEvent e){}
	public void mouseDragged(MouseEvent e){}
	public void mouseEntered(MouseEvent e) {}
	public void mouseExited(MouseEvent e) {}
	public void mouseClicked(MouseEvent e) {}
	public void mouseReleased(MouseEvent e) {}
}

Für Anregungen wäre ich äußerst dankbar!

seb
 

userSeb

Mitglied
Hallo,
den Code im Link schaue ich mir gleich an.
Warum eigentlich nie getGraphics()? Ich habe das erhlich gesagt auch nur durch Zufall eingefügt....
 
S

SlaterB

Gast
eine graphische Oberfläche wird vom System kontrolliert,
z.B. neugezeichnet wenn sich die Größe ändert, da ist deine einmalige Zeichung übermalt
 
S

SlaterB

Gast
gar nichts, du musst dich in den allgemeinen Zeichenablauf einklinken indem du paintComponent() überschreibst
Galileo Computing :: Java ist auch eine Insel (8. Auflage) – 17 Grafikprogrammierung


es bringt nichts, einem Kleinkind einmal die Schuhe zuzubinden, damit kommt es nicht durchs Leben,
an unterschiedlichen Zeiten muss das wieder geschehen, z.B. am nächsten Tag, deshalb dem Kind beibringen, selber die Schuhe zuzubinden,

einem Swing-Programm musst du beibringen, jederzeit die GUI kompetent darstellen zu können,
einmal was zu malen bringt wenig, es sei denn auf einem Image, welches immer wieder dargestellt wird (was dann auch zu programmieren wäre)
 

userSeb

Mitglied
ich bin verwirrt... warum genau geht es jetzt - selbst mit der methode zeichnen()?

Java:
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.*;

public class Main extends JFrame
{
	public static void main(String[] args)
	{	
		new Zeichenfeld();

	}
}	

class Zeichenfeld extends JFrame implements MouseListener
{
	//private int x = 5;
	//private int y = 5;

	public Zeichenfeld()
	{	
		setTitle("Zeichenfeld");
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setLocation(50,50);
		setSize(Toolkit.getDefaultToolkit().getScreenSize().width-100,Toolkit.getDefaultToolkit().getScreenSize().height-100);
		

		setVisible(true);
		addMouseListener(this);
	}

	public void mousePressed(MouseEvent e)
	{	
		int radius=100;
		int x = e.getX();
		int y = e.getY();
		zeichnen(getGraphics(),x,y,radius);	
		paintComponent(getGraphics(),x,y, radius);
	}
	

	public void zeichnen(Graphics g, int x1, int y1, int radius) 
	{
	    g.setColor(new Color(0, 0, 0));
	    g.drawOval(x1-(radius/2), y1-(radius/2), radius, radius);
	}

	public void paintComponent(Graphics g, int x1, int y1, int radius)
	{
		g.drawOval(x1-(radius/4), y1-(radius/4), (radius/2), (radius/2));
	}


	public void mouseMoved(MouseEvent e){}
	public void mouseDragged(MouseEvent e){}
	public void mouseEntered(MouseEvent e) {}
	public void mouseExited(MouseEvent e) {}
	public void mouseClicked(MouseEvent e) {}
	public void mouseReleased(MouseEvent e) {}
}
 
S

SlaterB

Gast
du hast den Aufruf
> paintComponents(g);
herausgenommen, der unter anderem den Bildschirm löscht,

ansonsten bist du noch bei der getGraphics()-Variante, alles was du zeichnest ist solange zu sehen, bis Swing es irgendwann mal löscht,
z.B. bei Größenänderung der GUI
 

Landei

Top Contributor
Hier mal ein ganz grober Entwurf:

Java:
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.*;

class Zeichenfeld extends JFrame {

    private List<Kreis> kreise = new ArrayList<Kreis>();
    private MouseListener listener = new MouseAdapter() {
        private Random random = new Random();

        @Override
        public void mousePressed(MouseEvent e) {
            Color color = new Color(random.nextInt(255),random.nextInt(255), random.nextInt(255));
            int radius = random.nextInt(100) + 50;
            kreise.add(new Kreis(e.getX(), e.getY(), radius, color));
            Zeichenfeld.this.repaint();
        }
    };

    public Zeichenfeld() {
        setTitle("Zeichenfeld");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLocation(50, 50);
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        setSize(screenSize.width - 100, screenSize.height - 100);
        setVisible(true);
        addMouseListener(listener);
    }

    public void paint(Graphics g) {
        for(Kreis kreis : kreise) {
            g.setColor(kreis.color);
            g.drawOval(kreis.x - (kreis.radius / 4),
                       kreis.y - (kreis.radius / 4),
                       kreis.radius / 2, kreis.radius / 2);
        }
    }

    private static class Kreis {
        final int x;
        final int y;
        final int radius;
        final Color color;

        public Kreis(int x, int y, int radius, Color color) {
            this.x = x;
            this.y = y;
            this.radius = radius;
            this.color = color;
        }
    }

    public static void main(String ... args) {
        new Zeichenfeld();
    }
}

Der Listener ist jetzt in einer eigenen (hier anonymen) Klasse. Vorteil: Ich kann von MouseAdapter erben, wodurch ich die ungenutzen MouseListener-Methoden nicht implementieren muss. Alle Kreise werden in einer Liste gespeichert. In deiner Variante würde eine Liste von java.awt.Point reichen, aber eine eigene Kreis-Klasse ist komfortabler, da man gleich Radius und Farbe mit unterbringen kann. Als kleine Anregung habe ich diese zufällig ausgewählt. Damit da Ganze für ein JFrame funktioniert, musste ich paint überschreiben, was allgemein (und in den JavaDocs) als schlechter Stil angesehen wird.

Die "richtige" Lösung wäre, Frame und Zeichenfläche zu trennen, die Kreis-Liste und den MouseListener an die Zeichenfläche zu hängen und für diese paintComponent zu überschreiben. Diese Zeichenfläche würde dann dem Frame hinzugefügt.
 

André Uhres

Top Contributor
Es zeigt bei mir zu Begin den Hintergrund des Bildschirms als Frameinhalt. Ich habe das Beispiel hier angepasst:
Java:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import javax.swing.*;

class Zeichenfeld extends JPanel {

    private final List<Kreis> kreise = new ArrayList<Kreis>();
    private final MouseListener listener = new MouseAdapter() {

        private Random random = new Random();

        @Override
        public void mousePressed(final MouseEvent e) {
            Color color = new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255));
            int radius = random.nextInt(100) + 50;
            kreise.add(new Kreis(e.getX(), e.getY(), radius, color));
            repaint();
        }
    };

    public Zeichenfeld() {
        addMouseListener(listener);
    }

    @Override
    protected void paintComponent(final Graphics g) {
        super.paintComponent(g);
        for (Kreis kreis : kreise) {
            g.setColor(kreis.getColor());
            int radius = kreis.getRadius();
            g.drawOval(kreis.getX() - (radius / 4),
                    kreis.getY() - (radius / 4),
                    radius / 2, radius / 2);
        }
    }

    public static void main(final String... args) {
        Runnable gui = new Runnable() {

            public void run() {
                createAndShowGui();
            }
        };
        //GUI must start on EventDispatchThread:
        SwingUtilities.invokeLater(gui);
    }

    private static void createAndShowGui() {
        Zeichenfeld zeichenfeld = new Zeichenfeld();
        JFrame f = new JFrame("Zeichenfeld");
        f.add(zeichenfeld);
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.setSize(400, 300);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class Kreis {

    private final int x;
    private final int y;
    private final int radius;
    private final Color color;

    public Kreis(final int x, final int y, final int radius, final Color color) {
        this.x = x;
        this.y = y;
        this.radius = radius;
        this.color = color;
    }

    public Color getColor() {
        return color;
    }

    public int getRadius() {
        return radius;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
}

Gruß,
André
 

userSeb

Mitglied
Apropos stilistisch (passt zwar nicht zum Ursprungsthema, aber will die Frage trotzdem hier stellen...)

Ist sowas in Ordnung:

Java:
import javax.swing.*;


public class SubJFrame extends JFrame
{
	public SubJFrame()
	{
		setSize(300,300);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setLocation(500, 500);
		setVisible(true);
	}
	
	public SubJFrame(String s)
	{
		new SubJFrame().setTitle(s);
		
	}
}
 

eRaaaa

Top Contributor
Du erstellst im Konstruktor ein neues Objekt? Schlecht und macht kein Sinn
Java:
class SubJFrame extends JFrame {
	public SubJFrame() {
		this("");
	}

	public SubJFrame(String s) {
		setSize(300, 300);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setLocation(500, 500);
                setTitle(s);
		setVisible(true);
	}
}
 

userSeb

Mitglied
ruft
Java:
 this ("")
den anderen Konstruktor auf und übergibt einen lehren String?

p.s
der String soll den Title setzen, also hab ich noch in den zweiten Konstruktor setTitle(s) eingefügt....
 

André Uhres

Top Contributor
der String soll den Title setzen, also hab ich noch in den zweiten Konstruktor setTitle(s) eingefügt....

"setTitle(s)" wird ja auch in der Lösung von eRaaaa aufgerufen.

Der Konstruktor ohne Parameter ist in deinem Fall allerdings nicht unbedingt nötig. Die Lösung von eRaaaa funktioniert auch, wenn er nicht da ist, denn er ruft ja lediglich den anderen Konstruktor mit einem Defaultparameter auf, für den Fall wo man den Titel noch nicht kennt (was eher unwahrscheinlich ist).

Gruß,
André
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
R 3D-Grafik Verwendung mehrerer Texturen AWT, Swing, JavaFX & SWT 1
R Auswahl mehrerer JComboBoxen verknüpfne AWT, Swing, JavaFX & SWT 17
D JavaFX Drag&Drop mehrerer TreeViews oder TableViews AWT, Swing, JavaFX & SWT 1
A Swing Einrücken mehrerer Zeilen per Tab in einem JTextPane/JTextArea AWT, Swing, JavaFX & SWT 3
V Fertige Komponente zum Anzeigen mehrerer Bilder AWT, Swing, JavaFX & SWT 5
Furtano AWT Skalierung mehrerer Bilder / Histogramme im Fenster AWT, Swing, JavaFX & SWT 4
K richtiges Ausrichten mehrerer Labels AWT, Swing, JavaFX & SWT 3
M Ansätze zur Kombination mehrerer Listener für Interaktion AWT, Swing, JavaFX & SWT 19
M auslesen mehrerer JComboBoxen funktioniert nicht AWT, Swing, JavaFX & SWT 9
M Swing Selektion mehrerer JToggleButton's in einer Gruppe AWT, Swing, JavaFX & SWT 5
S Swing JTable Auswahl mehrerer Zellen mit STRG+Maus AWT, Swing, JavaFX & SWT 3
G Darstellungsproblem mehrerer Komponenten AWT, Swing, JavaFX & SWT 9
D Überwachung mehrerer Textfelder AWT, Swing, JavaFX & SWT 4
S Aufbau mehrerer verschiedener grafischer Oberflächen AWT, Swing, JavaFX & SWT 2
M Hough-Transformation für Kreise und andere Formen AWT, Swing, JavaFX & SWT 3
G AWT AWT Kreise permanent anzeigen AWT, Swing, JavaFX & SWT 3
C JavaFX mehrere Kreise nach Eingabeprozess ausgeben AWT, Swing, JavaFX & SWT 2
P Bestimmte Kreise färben AWT, Swing, JavaFX & SWT 3
wolfgang63 JavaFX Animation, Kreise im vorgegebem Takt durchs Fenster laufen lassen AWT, Swing, JavaFX & SWT 3
J Swing Bild laden, Kreise drin malen, Schreiben AWT, Swing, JavaFX & SWT 2
M Kreise zeichnen AWT, Swing, JavaFX & SWT 6
E Swing Rechteck und Kreise verschieben AWT, Swing, JavaFX & SWT 3
M Kreise anklicken (Farbänderung) AWT, Swing, JavaFX & SWT 2
P Kreise Rechtecke AWT, Swing, JavaFX & SWT 5
G Swing Kreise auf JPanel zeichnen AWT, Swing, JavaFX & SWT 11
1 GeneralPath-Kreise werden keine Kreise AWT, Swing, JavaFX & SWT 2
M In einem JLabel Kreise zeichnen AWT, Swing, JavaFX & SWT 4

Ähnliche Java Themen

Neue Themen


Oben