Ein wenig zeichnen

Status
Nicht offen für weitere Antworten.

atticus2006

Mitglied
Hallo,

ich möchte ein kleines Programm schreiben, welches aus einem Menü besteht und durch anklicken verschiedene Gegenstände auf die Zeichenfläche malt. Wurde das Objekt gemalt, dann erscheint auch ein Button und mit diesem kann ich zwischen zwei Farben für das Objekt hin und her schalten.

Ich möchte gerne im linken Bereich ein Dreieck, im mittleren Bereich ein Krei und in den rechten Bereich ein Rechteck. Dazu habe ich die folgenden drei Klassen, welche von JPanel erben:

Java:
class ZeichneDreieck extends JPanel {
	public void paintComponent(Graphics g) {
		if (dreieckblau)
			g.setColor(Color.RED);
		else
			g.setColor(Color.BLUE);
		Polygon poly = new Polygon();
		poly.addPoint(10,10);
		poly.addPoint(100,10);
		poly.addPoint(50,110);
		poly.addPoint(10,10);
		g.fillPolygon(poly);
}


class ZeichneKreis extends JPanel {
	public void paintComponent(Graphics g) {
		if (kreisblau)
			g.setColor(Color.RED);
		else
			g.setColor(Color.BLUE);
		g.fillOval(10,10,100,100);
}


class ZeichneRechteck extends JPanel {
	public void paintComponent(Graphics g) {
		if (rechteckblau)
			g.setColor(Color.RED);
		else
			g.setColor(Color.BLUE);
		g.fillRect(10,10,100,150);
}

Doch wie mache ich es jetzt, dass die Koordinaten nicht fest vorgegeben sind, sondern sich an der jeweiligen Position auf dem Frame orientieren?
Außerdem werden mir die drei Dinge auch nicht angezeigt...

Kann mir jemand helfen?
 

KrokoDiehl

Top Contributor
Zum Einen brauchst du eine Zeichenfläche, auf die deine Komponenten gelegt werden müssen. Ein einfaches JPanel mit null-Layout sollte es hier tun.
Diesem Panel musst du deine Zeichenobjekte hinzufügen (via
Code:
add()
) und dabei deren bounds setzen.

Wie du diese setzt, ist im Grunde nur Mathematik. Du hast die Größe der Zeichenfläche (Breite und Höhe) und kannst dann selbst ausrechnen, wie und wo du deine Objekte hinhaben willst.

Damit kannst du in deinen Zeichenobjekten das Polygon z.B. schon direkt im Konstruktor berechnen. Jedesmal ein neues in
Code:
paintComponent()
erstellen ist eher unschön.

In Pseudocode stelle ich mir das wie folgt vor:
Java:
JPanel zeichenFlaeche = new JPanel(null);
myFrame.add(zeichenFlaeche, BorderLayout.CENTER); //bzw. entsprechendes

// ... beim Hinzufügen:
Rectangle groesse = new Rectangle(10, 10, zeichenFlaeche.getWidth() / 3, zeichenFlaeche.getHeight() / 2);
ZeichneDreieck dreieck = new ZeichneDreick(groesse);
zeichenFlaeche.add(groesse); //wichtig, sonst werden sie nicht gezeichnet

//... Dreieck:

class ZeichneDreieck extends JPanel
{
    protected Polygon meineForm = null;
    public ZeichneDreieck(Rectangle groesse)
    {
        meineForm = new Polygon();
        // ... Polygon aufbauen

        this.setBounds(groesse); //wichtig
    }

Ich denke das sollte als Denkanstoß genügen :)
 

atticus2006

Mitglied
Hallo,

schon einmal vielen Dank für deine Nachricht.

Reicht es denn eine einzige Zeichenfläche zu bauen, oder muss man drei Zeichenflächen benutzen?

Das Rechteck groesse dient also zur Begrenzung des Dreiecks und nicht etwas zum Zeichnen des Dreiecks selbst, oder?
 

KrokoDiehl

Top Contributor
Eine Zeichenfläche reicht, so wie ich dein Vorhaben verstehe.
Und ja, das
Code:
setBounds()
sagt dem Zeichenobjekt, wie groß es ist. Es ist quasi der Erstatz zum LayoutManager, wobei die x- und y-Angaben nur der Positionierung innerhalb der Zeichenfläche dienen.
Innerhalb des Zeichenobjekts kannst du mit
Code:
getWidth()
und
Code:
getHeight()
abfragen wie groß dein Zeichenobjekt ist (in Pixeln) und deine Polygonpunkte (oder sonstige Geometrie) entsprechend ausrichten.
 

atticus2006

Mitglied
Hallo,

noch einmal vielen Dank. Wie ist es mir denn jetzt Möglich die Farbe des Dreiecks zu verändern. Da ich ja nicht mehr das (Graphics g) habe, kann ich ja auch leider nicht mehr g.setColor(Color.RED) aufrufen.
 

KrokoDiehl

Top Contributor
Da ich ja nicht mehr das (Graphics g) habe, kann ich ja auch leider nicht mehr g.setColor(Color.RED) aufrufen.
...doch, die
Code:
paintComponent()
-Methode musst du dennoch überschreiben, wenn dein Panel eigene Figuren malen soll.
 

atticus2006

Mitglied
Leider habe ich die Aufgaben falsch verstanden, denn es sollen mehrere Objekte (Kreise, Quadrate, Dreiecke) gezeichnet werden können. Man wählt also über ein Menü z.B. Dreieck aus und jedes Mal, wenn man auf die Zeichenfläche klickt, wird ein kleines Dreieck gezeichnet. Anschließend kann man ein Objekt auswählen um für dieses die Farbe zyklisch zu ändern mittels eines Buttons (für Dreiecke, Quadrate und Kreise jeweils einen separaten Button).
Nun stehe ich natürlich ein wenig auf dem Schlauch, da ich zum Beispiel nicht weiß, wie ich das Dreieck auf Mausklick zeichnen kann und später dann auch noch selektieren kann.
 

KrokoDiehl

Top Contributor
Nun.
Du hast drei Klassen für je eine geometrische Figur, die sich selbst zeichnen kann. Über einen MouseListener an der Zeichenfläche kannst du rausbekommen, wohin der Benutzer geklickt hat. Diesen Punkt kannst du dann als Mittelpunkt, oder als oben/rechten Punkt für die jeweilige Figur nehmen:
Java:
// bitte als Pseudocode beachten!

//... Ereignisbehandlung
Point p = event.getPoint();
Dreieck d = new Dreieck(p);
zeichenFlaeche.add(d);


//... Bsp. für Dreieck
class Dreieck extends JPanel
{
    public Dreieck(Point anker)
    {
        super();
        setBounds(anker.x, anker.y, 50, 50); //Bsp für Std-Größe des Dreiecks
        //Dreieckpunkte berechnen
    }

    protected void paintComponent(Graphics g)
        //...
}
 

atticus2006

Mitglied
Hallo,

ich würde vorschlagen, dass wir uns zunächst auf das Rechteck stürzen, weil dieses doch ein wenig einfacher ist...

Java:
class Rechteck extends JPanel {
	    public Rechteck(Point anker) {
	        super();
	        setBounds(anker.x, anker.y, 50, 50);
	    }
	 
	    protected void paintComponent(Graphics g) {
	    	g.setColor(Color.BLUE);
	    	g.fillRect(10, 10, 5, 10);
	    }
	}
Java:
	public void mouseClicked(MouseEvent arg0) {
		Point p = arg0.getPoint();
		Rechteck r = new Rechteck(p);
		drawPanel.add(r);
		
	}

Nun müsste doch eigentlich immer wenn ich auf meine Zeichenfläche klicke ein Rechteck gezeichnet werden, aber leider passiert überhaupt nichts. In kann so viel klicken, wie ich will, aber leider passiert nichts... Woran kann das liegen?
 

KrokoDiehl

Top Contributor
Java:
        protected void paintComponent(Graphics g) {
            g.setColor(Color.BLUE);
            g.fillRect(10, 10, 5, 10);
        }
Dein Rechteck-Panel hat die Größe 50x50 (s. Konstruktor). Innerhalb der Komponente (also in der o.g. Methode) greifst du nur noch auf lokale Koordinaten zu. Sprich, wenn du willst dass dein ganzes Panel ausgefüllt wird, muss der Aufruf wie folgt aussehen:
Java:
 g.fillRect(0, 0, this.getWidth(), this.getHeight());
Wenn dein drawPanel noch irgendwo ein null-Layout bekommt
Java:
drawPanel = new JPanel(null);
oder
drawPanel.setLayout(null);
sehe ich sonst keine Probleme.
 

atticus2006

Mitglied
Moin,

also sp richtig was passiert lieder immer noch nicht. Ich poste mal die relevanten Stellen meines bisherigen codes.

Java:
JFrame frame = new JFrame();
JPanel drawPanel = new JPanel(null);

Java:
public void makeFrame() {
	frame.setTitle("Bunte Knöpfe");
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	frame.setSize(500, 300);
	frame.add(BorderLayout.CENTER, drawPanel);
	frame.setVisible(true);
}

Java:
class Rectangle extends JPanel
{
    public Rectangle(Point anchor)
    {
        super();
        setBounds(anchor.x, anchor.y, 50, 50);
    }
 
    protected void paintComponent(Graphics g) {
    	g.setColor(Color.BLUE);
    	g.fillRect(0, 0, this.getWidth(), this.getHeight());
    }
}

Java:
public void mouseClicked(MouseEvent arg0) {
	Point p = arg0.getPoint();
	Rectangle r = new Rectangle(p);
	drawPanel.add(r);
	
}

Aber es passiert beim Klicken leider gar nichts...
 

KrokoDiehl

Top Contributor
Damit das mal zu einem Ende kommt... ;)

Das folgende Programm läuft bei mir. Ich habe auch erst gemerkt, dass ein
Code:
repaint()
nach dem Klick fehlte. Ohne das sieht man das Rechteck erst nach Vergrößern des Fensters.
Ansonsten habe ich in deinen Code-Stellen nicht gesehen, ob der MouseListener auch der Zeichenfläche hinzugefügt wird.

Also, das folgende Beispiel tut bei mir, ohne jedoch Anspruch auf Schönheit zu haben ;)
Java:
public class Test
{
	static class Rechteck extends JPanel
	{
		public Rechteck(Point p)
		{
			super();
			this.setBounds(p.x, p.y, 50, 50);
		}
		
		@Override
		protected void paintComponent(Graphics g) 
		{
			g.setColor( Color.blue );
			g.fillRect(0, 0, this.getWidth(), this.getHeight());
		}
	}
	
	public static void main(String[] args) 
	{
		final JPanel pane = new JPanel(null);
		pane.setBackground( Color.white );
		pane.setPreferredSize(new Dimension( 200, 200));
		pane.addMouseListener(new MouseAdapter() 
		{
			@Override
			public void mouseClicked(MouseEvent event) 
			{
				Rechteck r = new Rechteck(event.getPoint());
				pane.add(r);
				pane.repaint( r.getBounds() );
			}
		});
		
		final JFrame frame = new JFrame("Zeichnen");
		frame.add(pane, BorderLayout.CENTER);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		SwingUtilities.invokeLater(new Runnable()
		{
			@Override
			public void run() 
			{
				frame.pack();
				frame.setVisible(true);
			}
		});
	}
}
 

atticus2006

Mitglied
Hallo,

vielen Dank. Hatte tatsächlich nur vergessen den MouseClick-Listener zu starten. Jetzt klappt alles und ich kann schon das Rechteck und die Kreise zeichnen, nur an den Dreiecken harpert es noch, da ich noch nicht weiß, wie ich die einzelnen Punkte in Abhängigkeit meines Mausklicks berechnen muss. Gibt es dafür einen TricK?

bunteknoepfe.png


Wenn ich zunächst nur Kreise zeichne, habe die keinen Hintergrund, sobald ich aber ein Rechteck gemalt habe, erscheint bei den danach gezeichneten Kreisen blaue Ecken, warum?
 

icarus2

Top Contributor
Du bekommst den Punkt S(x; y) durch den MouseListener (die Koords, wo gelickt wurde).
Der Punkt S ist dabei der Schwerpuntk des Dreiecks.
Die Variable w steht für die Breite des Dreiecks (sie ist ein konstanter Wert, den du eingeben musst).
Die Variable h steht für die Höhe im Dreieck.
Die Punkte A, B, C stellen die Eckpunkte des Dreiecks dar.

Wenn das Dreieck gleichseitig ist (ich gehe davon aus, dass das bei dir der Fall sein wird, dann gilt folgendes):

h = (w^2 - (w / 2)^2)^(1/2)

Eckpunkte:
A(x ; y - 2/3 * h)
B(x - w/2 ; y + h / 3)
C(x + w/2 ; y + h / 3)

Zur Methode paintComponent:
Die Methode paintComponent(...) sollte immer folgende Struktur haben:
[Java]
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);

//...
}
[/Java]
Es muss unbedingt die paintComponent(...) Methode der Superklasse aufgerufen werden.

*Edit:
Ich habe das ganze übrigens nicht getestet. Aber ich denke es müsste funktionieren. Die x und y Werte, die ich angegeben habe, sind bereits auf das Koordinatensystem von Java umgerechnet.
 
Zuletzt bearbeitet:

atticus2006

Mitglied
Danke, das mit dem Aufruf von
Code:
super.paintComponent(g)
hat geholfen, aber nun hänge ich noch ein wenig beim Dreieck. Wie greife ich denn auf die vom MouseListener übergebenen Werte innerhalb meiner Klasse
Code:
Dreieck()
drauf zu? Ich habe ja nicht, wie beim Konstruktor die Möglichkeit die Points zu erhalten, oder sehe ich den Wald vor lauter Bäumen schon wieder nicht...
 

icarus2

Top Contributor
Du speicherst am besten eine Instanz der Klasse Point als Instanzvariable.

[Java]
public class TriangleDrawer extends JFrame implements MouseListener {

Point s = new Point();
JPanel panel;

//Constructor
public TriangleDrawer(){
//....
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
new TriangleDrawer();
}
});

}

@Override
public void mouseClicked(MouseEvent e) {}

@Override
public void mouseEntered(MouseEvent e) {}

@Override
public void mouseExited(MouseEvent e) {}

@Override
public void mousePressed(MouseEvent e) {}

@Override
public void mouseReleased(MouseEvent e) {

s.x = e.getX();
s.y = e.getY();

panel.repaint();

}

}
[/Java]

Anschliessen kannst du in der Methode paintComponent(..) auf das das Point-Objekt zugreiffen.
 

atticus2006

Mitglied
Irgendwie zeichnet er mir jetzt gar nichts mehr, wenn ich ein Dreieck haben möchte...

Java:
	class Triangle extends JPanel {

		public Triangle(Point p) {
			super();
			this.setBounds(p.x, p.y, 25, 25);
		}

		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			g.setColor(Color.GREEN);
			Polygon poly = new Polygon();
			int h = 25;
			poly.addPoint(s.x, s.y - (2/3)*h);
			poly.addPoint(s.x-25/2, s.y+h/3);
			poly.addPoint(s.x + 25 / 2, s.y + h / 3);
			poly.addPoint(s.x, s.y - (2 / 3) * h);
			g.fillPolygon(poly);
			super.paintComponent(g);
			System.out.println(h);

		}
	}
}
 

icarus2

Top Contributor
Nimm das zweite super.paintComponent(g) raus. In der Methode werden Aufräumarbeiten erledigt, wodurch die Dreiecke wieder gelöscht werden.

So:
[Java]
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
Polygon poly = new Polygon();
int h = 25;
poly.addPoint(s.x, s.y - (2/3)*h);
poly.addPoint(s.x-25/2, s.y+h/3);
poly.addPoint(s.x + 25 / 2, s.y + h / 3);
poly.addPoint(s.x, s.y - (2 / 3) * h);
g.fillPolygon(poly);
System.out.println(h);

}
[/Java]
 

atticus2006

Mitglied
Leider werden trotzdem keine Dreiecke gezeichnet...
Die Kreise und die Rechtecke funktionieren ohne Probleme, aber die Dreiecke wollen einfach nicht.
 

icarus2

Top Contributor
Hier habe ich etwas Code, bei dem die Dreiecke gezeichnet werden:

[Java]
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.TitledBorder;


public class TriangleDrawer extends JFrame implements MouseListener {

Container c;
JPanel panel;
Point s;

private final static int TRIANGLE_WIDTH = 200;
private static int triangleHeight;

public TriangleDrawer(){

triangleHeight = (int) (Math.sqrt(Math.pow(TRIANGLE_WIDTH, 2) - Math.pow(TRIANGLE_WIDTH/2, 2)));
s = new Point();

//GUI
c = getContentPane();

panel = new JPanel(){

@Override
public void paintComponent(Graphics g){
super.paintComponent(g);

Polygon p = new Polygon();
p.addPoint(s.x, s.y - 2 * triangleHeight / 3);
p.addPoint(s.x - TRIANGLE_WIDTH / 2, s.y + triangleHeight / 3);
p.addPoint(s.x + TRIANGLE_WIDTH / 2, s.y + triangleHeight / 3);

g.drawPolygon(p);
}

};
panel.setLocation(0, 0);
panel.setBorder(new TitledBorder("Panel"));
panel.setSize(this.getSize());

c.add(panel);

addMouseListener(this);

setSize(500, 500);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
new TriangleDrawer();
}
});

}

@Override
public void mouseClicked(MouseEvent e) {}

@Override
public void mouseEntered(MouseEvent e) {}

@Override
public void mouseExited(MouseEvent e) {}

@Override
public void mousePressed(MouseEvent e) {}

@Override
public void mouseReleased(MouseEvent e) {

s.x = e.getX();
s.y = e.getY();

panel.repaint();

}

}

[/Java]

*Edit
Die Dreiecke sind in meinem Beispiel leider nicht gleichseitig. Ich habe da wohl irgendwo einen kleinen Fehler gemacht. Aber den wirst du bestimmt finden.

*Edit 2
Code funktioniert jetzt einwandfrei.
 
Zuletzt bearbeitet:

atticus2006

Mitglied
Stimmt, dein Code funktioniert, aber leider funktioniert die Integration in mein Projekt immer noch nicht. Muss denn der MouseListener von der Klasse selbst implementiert werden? Ich habe das jetzt einfach in dem anderen MouseListener und die Werte werden auch übergeben, was ein kurzes System.out.println(s.x + " " + s.y) verrät, aber leider erscheint kein grünes Dreieck...
 

icarus2

Top Contributor
Hmm, zeige mal etwas Quellcode. Schau mal was du für Werte hast in der Methode paintComponent(...). Bist du sicher, dass du überall mit den gleichen Objekten arbeitest?
 

atticus2006

Mitglied
Hier also der relevante Code:

Java:
	    private final static int TRIANGLE_WIDTH = 200;
	    private int triangleHeight = 0;
	    

		public Triangle(Point p) {
			super();
			this.setBounds(p.x, p.y, 50, 50);
		}

		public void paintComponent(Graphics g) {
			
			int triangleHeight = (int) (Math.sqrt(Math.pow(TRIANGLE_WIDTH, 2)
					- Math.pow(TRIANGLE_WIDTH / 2, 2)));

			super.paintComponent(g);

			g.setColor(Color.GREEN);

			Polygon p = new Polygon();
			p.addPoint(s.x, s.y - 2 * triangleHeight / 3);
			p.addPoint(s.x - TRIANGLE_WIDTH / 2, s.y + triangleHeight / 3);
			p.addPoint(s.x + TRIANGLE_WIDTH / 2, s.y + triangleHeight / 3);

			g.fillPolygon(p);

		}

	}

Java:
	public void mouseClicked(MouseEvent mouseevent) {
		
		

		if (triangle) {
			
	        s.x = mouseevent.getX();
	        s.y = mouseevent.getY();

	        System.out.println(s.x + "  " + s.y);
			
			Triangle t = new Triangle(mouseevent.getPoint());
			drawPanel.add(t);
			drawPanel.repaint(t.getBounds());
		}
       }
 

KrokoDiehl

Top Contributor
[JAVA=8]
this.setBounds(p.x, p.y, 50, 50);
[/code]
Hier sagst du, dass dein Triangle insgesamt eine Fläche von 50x50 Pixeln zur Verfügung haben soll, mehr nicht. D.h. deine Definiton von
Code:
TRIANGLE_WIDTH = 200;
kann gar nicht angewendet werden.

In der
Code:
paintComponent()
-Methode musst du Bezug nehmen auf die Größe deines Panels. Du hast beim Zeichnen nur die Fläche zur Verfügung, die du mit
Code:
setBounds()
angibts:
Von Punkt
Code:
(0, 0)
(links oben) bis
Code:
(getWidth(), getHeight())
(in dem Fall
Code:
(50, 50)
). Dies ist das lokale Koordinatensystem des Triangle-Panels.
D.h. dass dein berechnetes Polygon in
Code:
paintComponent()
vermutlich außerhalb dieses Bereichs liegt und daher nicht gezeichnet wird / werden kann.

Die Berechnung vom Dreieck-Polygon solltest du in den Triangle-Konstruktor auslagern. Es bei jedem
Code:
paint()
neu berechnen zu lassen ist unnötig, weil immer das gleiche rauskommt.
Außerdem hast du im Konstruktor nach dem
Code:
 setBounds()
-Aufruf direkt den verfügbaren Bereich deines Triangle-Panels:
Java:
protected Polygon triangle = null;

public Triangle(Point p)
{
    super(null);    
    this.setBounds(p.x, p.y, TRIANGLE_WIDTH, TRIANGLE_WIDTH);
    // nun hast du einen verfügbaren Bereich von (0, 0) bis (200, 200)
    triangle = new Polygon();
    triangle.addPoint(0, 0); // oben links
    triangle.addPoint(TRIANGLE_WIDTH, 0); //oben rechts
    triangle.addPoint(TRIANGLE_WIDTH/2, TRIANGLE_WIDTH); //unten Mitte
}

protected void paintComponent(Graphics g)
{
    g.setColor( Color.blue );
    g.fillPolygon(triangle);
}
 

atticus2006

Mitglied
So, bisher läuft alles. Ich kann also mit dem Menü die verschiedenen geometrischen Figuren auswählen und auf der Schaltfläche zeichnen. Nun soll es noch möglich sein, dass ich nachträglich eines der gezeichneten Objekte markiere und per Buutton die Farbe verändert nach einem bestimmten Farbzyklus zwischen drei Farben.

Ich habe derzeit nur leider keine Idee, wie ich jetzt wieder schauen kann, ob eines der Objekte markiert ist. Gibt es dafür einen Trick?
 

icarus2

Top Contributor
Also ich würde mal alle geometrischen Figuren in einer Liste speichern und dazu auch die Farbe des jeweiligen Objekts.

1. Möglichkeit:
Du schreibst eine Methode, die nach einem Mausklick die am nächsten gelegene Figur findet und diese "selektiert", oder irgendwie angezeigt wird, dass diese Figur den Fokus hast. Dann kannst du z.B. per Button-Klick dann die Farbe der selektierten Figur geändert wird. Würde wohl ein repaint() sein für das Neuzeichnen.

2. Möglichkeit:
Wieder eine Liste machen. Du erstellst eine JComboBox, in der alle Figuren durchnummeriert sind. Anschliessed kannst du eine Figur selektieren, indem du sie in der JComboBox selektierst. (Wäre vielleicht etwas einfacher als eine eigene Methode zu schreiben). Analog zu oben dann der Button-Klick.

3. Möglichkeit:
Wieder eine Liste machen. Anschliessend einen Button, mit dem du dich durch die Liste klicken kannst, wodurch immer die nächste Figur in einer Liste selektiert wird (dazu musst du halt einfach etwas neben die Figur zeichnen um zu zeigen welche Figur selektiert ist). Dann wieder analog der Buttonklick.

PS:
Sind nur Anregungen, wie man es möglicherweise machen könnte. Gibt natürlich noch viele andere Möglichkeiten, vor allem was die Darstellung angeht. Hoffe aber, dass es dir ein bisschen hilft.
 

atticus2006

Mitglied
Hallo,

die Ideen sind auf jeden Fall schon einmal echt nicht schlecht. Ich denke, dass wohl die Möglichkeit 1 am Besten wäre, aber derzeit weiß ich noch nicht, wie ich das ganze in eine Liste packen kann, denn pro Figur muss ich ja speicher, wo sie liegt, was sie ist und welche Farbe sie hat, damit ich dann die nächste farbe auswählen kann.

Kannst du vielleicht beim generieren der Listeneinträge sagen, wie man diese zu wählen hat, dass es effektiv ist?
 

icarus2

Top Contributor
Eine Idee:
Erstelle für jede gemoetrische Figur eine eigene Klasse, z.B. Dreieck, Kreis oder welche Figur das auch immer sein mag. Alle diese Klassen implementieren das Interface GeometricalFigure.

GeometricalFigure:
[Java]
import java.awt.Graphics;


public interface GeometricalFigure {

void draw(Graphics g);

void setSelectionState(boolean state);

boolean isIselelected();

}
[/Java]

Anschliessend kannst du eine Liste erstellen mit folgenden Parametern:
[Java]
ArrayList<GeometricalFigure> list = new ArrayList<GeometricalFigure>();
[/Java]

Nun hat jedes Element in deiner Liste die 3 Methoden des Interface zur Verfügung. Auch wird dadurch die Methode paintComponent(Graphics g) einfach:
[Java]
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);

for(GeometricalFigure fig : list){
fig.draw(g);
}
}
[/Java]


In der draw(...)-Methode, die die Klassen implementieren müssen wegen dem Interface müssen dann halt nur noch Dinge stehen wie g.drawRect(...) und solche Dinge. Ich hoffe das hilft dir etwas.


*Edit:
Sry, hab den falschen Button geklickt, wollte nur Vorschau wählen... musst dich noch etwas Gedulden bis ich fertig bin ^^

*Edit 2:
So, jetzt aber ;-)
 
Zuletzt bearbeitet:

atticus2006

Mitglied
Hmmh.

Dann müsste ich ja alle meine derzeitigen Klassen wieder umschreiben und ich habe dann ja immer noch das Problem zu überprüfen, ob ein jeweiliges Element angeklickt wurde.
 

icarus2

Top Contributor
Wenn du deine Klassen von Rectangle2D ableitest, dann kannst du mit der Methode intersects(..) sehr gut überprüfen, ob etwas angeklickt wurde.

Ich stelle mir das so vor:
Du hast einen MouseListener. Wenn die Maus geklickt wurde, wird dieser aufgerufen. Dort speicherst du den Punkt wo geklickt wurde. Du erstellst anschliessend ein kleines Rechteck um den Punkt (das Rechteck ist eine Instanz von Rectangle2D). Anschliessend kannst du mit dasNeueRechtEck.instersects(rechtEckAusListe) überprüfen, ob eines angewählt wurde. Wenn ja bekommt dieses den Fokus... dafür hast ja entsprechende Methoden im Interface implementiert.

Weisst du was ich meine?
 

atticus2006

Mitglied
Also, kurze Zusammenfassung: Ich habe jetzt ein Frame mit einem Panel, auf dem ich per Mausklick verschiedene Objekte einzeichnen kann. Welches Objekt gezeichnet wird entscheide ich über ein Menü. Dieses funktioniert auch jetzt ohne Probleme.

Nun möchte ich ein einzelnes Objekt markieren. Dazu könnte man den MouseListener um folgendes ergänzen, wenn die Maus geklickt wurde:
Java:
public void mouseClicked(MouseEvent mouseevent) {
	Point s = new Point();
	s.x = mouseevent.getX();
	s.y = mouseevent.getY();
}

Doch wie geht es jetzt weiter. Wenn dieser Klick nun innerhalb eines Objektes war, dann soll dieses markiert werden und ein Button wird eingeblendet, über den man dann die Farbe des Objektes durch Klicken verändern kann...
 

icarus2

Top Contributor
Genau. Das Problem ist jetzt, dass deine anderen Klassen von Rectangle2D abgeleitet sein sollten. Weil dann könntest du jetzt aus dem Punkt ein kleines Rechteck (auch Rectangle2D-Objekt machen) und anschliessend in einer for-Schleife mit Hilfe der in der Rectangle2D geschriebenen Methode intersects überprüfen, welches Objekt denn angeklickt wurde. Das funktioniert aber nur, wenn die anderen Objekte in der Liste vom Typ Rectangle2D sind. Sonst funzt die Methode intersects nicht.
 

atticus2006

Mitglied
Okay, könntest du denn vielleicht die Klasse
Code:
Rectangle
anpassen, dass es von der Klasse
Code:
Rectangle2D
abhängt?

Java:
	class Rectangle extends JPanel {
		public Rectangle(Point p) {
			super();
			this.setBounds(p.x, p.y, 25, 25);
		}

		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			g.setColor(Color.BLUE);
			g.fillRect(0, 0, this.getWidth(), this.getHeight());

		}
	}
 

icarus2

Top Contributor
Ich habe jetzt einmal etwas gecodet:

Erst einmal die Hauptklasse:
[Java]
import java.awt.BorderLayout;
import java.awt.Container;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.border.TitledBorder;


public class Main extends JFrame {

Container c;

DrawingPanel drawingPanel;

protected Main(){

c = getContentPane();
c.setLayout(new BorderLayout());

drawingPanel = new DrawingPanel();
drawingPanel.setBorder(new TitledBorder("Drawing Panel"));


c.add(drawingPanel, BorderLayout.CENTER);


setSize(600, 400);
setLocationRelativeTo(null);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


}

public static void main(String[] args) {

SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
new Main();
}
});

}

}
[/Java]

Dann die Panel-Klasse:
[Java]
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

import javax.swing.JPanel;


public class DrawingPanel extends JPanel implements MouseListener, KeyListener{

ArrayList<RectangleFigure> figures = new ArrayList<RectangleFigure>();

Point clickCoords;
Rectangle2D.Double clickArea;

private static boolean ctrlPressed;

public DrawingPanel(){
clickCoords = new Point();
clickArea = new Rectangle2D.Double();

setFocusable(true);

addKeyListener(this);
addMouseListener(this);

}

@Override
public void paintComponent(Graphics g){
super.paintComponent(g);

for(Drawable d : figures){
d.draw(g);
}

}

public void checkIntersection(Rectangle2D.Double clickedRectangle){

for(int i = 0; i < figures.size(); i++){
if(clickedRectangle.intersects(figures.get(i))){
figures.get(i).setSelected(true);
break;
}else{
figures.get(i).setSelected(false);
}
}

}


@Override
public void mouseClicked(MouseEvent e) {
//if ctrl is pressed, there won't be any figures added
if(ctrlPressed){

clickCoords.x = e.getX();
clickCoords.y = e.getY();

clickArea.x = clickCoords.x - 10;
clickArea.x = clickCoords.y - 10;
clickArea.width = clickArea.x + 20;
clickArea.height = clickArea.x + 20;

checkIntersection(clickArea);

}else{
figures.add(new RectangleFigure(e.getX(), e.getY(), 50, 50, false));
repaint();
}

}

@Override
public void mouseEntered(MouseEvent e) {}

@Override
public void mouseExited(MouseEvent e) {}

@Override
public void mousePressed(MouseEvent e) {}

@Override
public void mouseReleased(MouseEvent e) {}

@Override
public void keyPressed(KeyEvent e) {

if(e.getKeyCode() == KeyEvent.VK_ALT){
ctrlPressed = true;
}

}

@Override
public void keyReleased(KeyEvent e) {

if(e.getKeyCode() == KeyEvent.VK_ALT){
ctrlPressed = false;
}

}

@Override
public void keyTyped(KeyEvent e) {}



}
[/Java]

2 Interfaces:
[Java]
public interface Selectable {

void setSelectionState(boolean state);

boolean isSelected();

}
[/Java]

[Java]

import java.awt.Graphics;

public interface Drawable {

void draw(Graphics g);

}
[/Java]

Diese Interfaces werden von dieser abstrakten Klasse implementiert (die abstrakte Klasse wird gebraucht, um die ArrayList typsicher zu machen):
[Java]
import java.awt.geom.Rectangle2D;


public abstract class Figure extends Rectangle2D.Double implements Drawable, Selectable {

private boolean selected;

public Figure(){

}

public Figure(int x, int y, int width, int height){
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}


public Figure(int x, int y, int width, int height, boolean selected){
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.selected = selected;
}

public boolean isSelected() {
return selected;
}

public void setSelected(boolean selected) {
this.selected = selected;
}
}
[/Java]

Und dann eine konkrete Klasse, die jeweils gebraucht wird. In diesem Fall ein Rechteck:
[Java]
import java.awt.Graphics;


public class RectangleFigure extends Figure {

public RectangleFigure() {

}

public RectangleFigure(int x, int y, int width, int height) {
super(x, y, width, height);

}

public RectangleFigure(int x, int y, int width, int height, boolean selected) {
super(x, y, width, height, selected);

}

@Override
public void draw(Graphics g) {

g.drawRect((int)x, (int)y, (int)width, (int)height);

}

@Override
public boolean isSelected() {
return isSelected();
}

@Override
public void setSelectionState(boolean state) {

setSelected(state);

}

}
[/Java]

So sollte es in etwas einigermassen sauber funktionieren. Schau es dir mal an und wenn etwas unkar sein sollte, dann frage ;-) Das Programm ist nicht fertig, sollte aber von der Klassenstruktur her nicht schlecht sein. Dadurch kannst du ohne Probleme beliebige Figuren hinzufügen. Natürlich fehlt die GUI so wie du sie möchtest und alles.
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
ARadauer Wenig Material zum Thema: Design, Layout, Usability von Swing Anwendungen AWT, Swing, JavaFX & SWT 11
T GridLayout, zu wenig Platz zwischen Widgets AWT, Swing, JavaFX & SWT 3
G Text in JTable ein wenig nach rechts verrücken? AWT, Swing, JavaFX & SWT 4
M Mandelbrot mit BigDecimal erstellen und in der UI zeichnen, funktionierte nicht. AWT, Swing, JavaFX & SWT 1
H JavaFX Canvas neu zeichnen anstoßen AWT, Swing, JavaFX & SWT 34
H Transparent zeichnen mit drawImage in paintComponent Methode AWT, Swing, JavaFX & SWT 3
N JavaFX Unicode zeichnen in javafx Label verwenden AWT, Swing, JavaFX & SWT 2
G 2D-Grafik Grafik in zwei verschiedenen Fenstern gleichzeitig zeichnen AWT, Swing, JavaFX & SWT 9
S Event Handling Neu zeichnen nur wenn Berechnung fertig ist AWT, Swing, JavaFX & SWT 4
W JavaFX Ich kann keinen Kreis richtig zeichnen AWT, Swing, JavaFX & SWT 8
CptK Funktionsgraphen effizient zeichnen und nur Teile von JPanel erneuern AWT, Swing, JavaFX & SWT 2
G Dreieck aus Pixeln zeichnen AWT, Swing, JavaFX & SWT 8
N Mit KeyListener ein rechteck zeichnen AWT, Swing, JavaFX & SWT 9
B 2D-Grafik paintcomponent Probleme beim zeichnen AWT, Swing, JavaFX & SWT 10
Z Swing Graph zeichnen lassen AWT, Swing, JavaFX & SWT 16
O Kann kei neues Panel zum zeichnen aufrufen... AWT, Swing, JavaFX & SWT 4
L Swing zeichnen AWT, Swing, JavaFX & SWT 14
S GUI Kreuz zeichnen und Position ausgeben AWT, Swing, JavaFX & SWT 3
S GUI Kreis zeichnen AWT, Swing, JavaFX & SWT 13
S Swing Rechteck über JTable zeichnen (per MouseListener) AWT, Swing, JavaFX & SWT 1
L Swing Ein Rechteck in ein Grid Zeichnen AWT, Swing, JavaFX & SWT 5
L JavaFX Animation, erst zeichnen dann anzeigen AWT, Swing, JavaFX & SWT 4
K Mehrere Linien zeichnen AWT, Swing, JavaFX & SWT 8
E Transparent zeichnen AWT, Swing, JavaFX & SWT 2
S AWT Probleme beim Zeichnen AWT, Swing, JavaFX & SWT 3
T Tic Tac Toe - GUI Linien zeichnen AWT, Swing, JavaFX & SWT 14
C Applet Zeichnen über Button-Click AWT, Swing, JavaFX & SWT 13
Soloeco Graph zeichnen AWT, Swing, JavaFX & SWT 1
G Zeichnen Programm AWT, Swing, JavaFX & SWT 1
I Graph mit Swing zeichnen AWT, Swing, JavaFX & SWT 8
H Swing + Paint: Mehrere Objekte zeichnen lassen AWT, Swing, JavaFX & SWT 3
W Swing JPanel nur einmal nach mehreren Änderungen neu zeichnen AWT, Swing, JavaFX & SWT 1
D Quadrat, Rechteck zeichnen AWT, Swing, JavaFX & SWT 3
K Probleme beim zeichnen mit paintComponent() AWT, Swing, JavaFX & SWT 1
JG12111989 mehrere Polyline-Objekte zeichnen AWT, Swing, JavaFX & SWT 3
A Swing JRadioButton zeichnen nicht AWT, Swing, JavaFX & SWT 4
J Swing Vertikales Zeichnen eines Strings mit Java2D AWT, Swing, JavaFX & SWT 1
7 JavaFX Problem beim Zeichnen eines Dreiecks in einem GUI AWT, Swing, JavaFX & SWT 6
P 2D-Grafik Bogen(Arc) zwischen zwei Punkten zeichnen AWT, Swing, JavaFX & SWT 2
F Java Swing Rechteck in JPanel zeichnen AWT, Swing, JavaFX & SWT 7
KilledByCheese Swing 2D JLabel Array Maze zeichnen AWT, Swing, JavaFX & SWT 2
S Parallele Linien zeichnen AWT, Swing, JavaFX & SWT 5
J Linien auf JPanel zeichnen AWT, Swing, JavaFX & SWT 3
P AWT Canvas freihändig zeichnen AWT, Swing, JavaFX & SWT 1
llabusch Linien in JPanel zeichnen AWT, Swing, JavaFX & SWT 6
S passende PaintComponent ? Zeichnen in TextArea mit Scrollpane ? AWT, Swing, JavaFX & SWT 2
I Applet BlueJ Applet - Bild mit if-Schleife zeichnen lassen AWT, Swing, JavaFX & SWT 16
L JavaFX JavafX Timelime zeichnen und schön stylen? AWT, Swing, JavaFX & SWT 2
I JFrame neu zeichnen, nicht überzeichnen! AWT, Swing, JavaFX & SWT 2
I Spielsteine zeichnen und entfernen AWT, Swing, JavaFX & SWT 3
H JavaFX Freezes beim Zeichnen mit Canvas AWT, Swing, JavaFX & SWT 3
H Swing BufferedImage zeichnen AWT, Swing, JavaFX & SWT 1
M JFreeChart neu zeichnen sich Wenn Jtable sich ändert AWT, Swing, JavaFX & SWT 5
S 2D-Grafik MouseDragged Linien zeichnen AWT, Swing, JavaFX & SWT 4
M Zeichnen ohne vorherige Linien zu löschen AWT, Swing, JavaFX & SWT 2
T Problem beim Zeichnen von Rechteck AWT, Swing, JavaFX & SWT 3
T Swing / Kreis zeichnen AWT, Swing, JavaFX & SWT 2
I Text zur Linie zeichnen AWT, Swing, JavaFX & SWT 1
I Pfeil zeichnen am Ende einer Linie AWT, Swing, JavaFX & SWT 1
D 2D-Grafik Inhalt eines Graphics in anderes Graphics zeichnen.... AWT, Swing, JavaFX & SWT 3
F Zeichnen des Button AWT, Swing, JavaFX & SWT 4
B Zeichnen mit paintComponent? Oder anders? AWT, Swing, JavaFX & SWT 15
C Swing Aus verschiedenen Klassen zeichnen. AWT, Swing, JavaFX & SWT 2
C Swing BufferedImage zeichnen und JLabels setzen. AWT, Swing, JavaFX & SWT 17
M Kein Zeichnen der Figuren auf JPanel AWT, Swing, JavaFX & SWT 4
J JButton neu zeichnen lassen AWT, Swing, JavaFX & SWT 9
S Quadrat auf Frame zeichnen AWT, Swing, JavaFX & SWT 2
P Image oder Icon auf Tooltip zeichnen AWT, Swing, JavaFX & SWT 4
C Graphics Objekt in Zeitschleife zeichnen AWT, Swing, JavaFX & SWT 4
X Swing JPanel mehrere Ebenen zeichnen AWT, Swing, JavaFX & SWT 13
G Zeichnen auf eine schwergewichtige Komponente? AWT, Swing, JavaFX & SWT 0
G Mehrere Strings um Kreis zeichnen und positionieren AWT, Swing, JavaFX & SWT 0
P SWT Nebula Gallery - Bildbereiche zeichnen AWT, Swing, JavaFX & SWT 3
A Swing Paint mit Button Clear den Hintergrund säubern um wieder zeichnen zu können AWT, Swing, JavaFX & SWT 2
A 2D-Grafik Zeichnen einer sich bewegenden Box mit BufferStrategy zieht Spur AWT, Swing, JavaFX & SWT 2
T AWT Bild laden und transparent zeichnen AWT, Swing, JavaFX & SWT 2
Helgon Swing Mit Swing zeichnen / NetBeans GUI AWT, Swing, JavaFX & SWT 11
M JLabel über JButtons zeichnen AWT, Swing, JavaFX & SWT 4
J JApplet und Zeichnen AWT, Swing, JavaFX & SWT 8
P 2D-Grafik NPE beim Zeichnen auf Graphics g AWT, Swing, JavaFX & SWT 8
4 Swing Graphen selber zeichnen AWT, Swing, JavaFX & SWT 2
T Über mehrere Panel zeichnen AWT, Swing, JavaFX & SWT 2
T Zeichnen von getSubimage funktioniert nicht AWT, Swing, JavaFX & SWT 7
M Bilder zeichnen, NullPointer Exception AWT, Swing, JavaFX & SWT 3
N JPanel neu zeichnen AWT, Swing, JavaFX & SWT 10
D Zeichnen eines Barplots AWT, Swing, JavaFX & SWT 2
bluerob Problem beim Image zeichnen via andere Klasse AWT, Swing, JavaFX & SWT 7
M Swing JFrame in einem Panel zeichnen AWT, Swing, JavaFX & SWT 3
M Suche Javabibliothek zum Zeichnen mathematischer Funktionen AWT, Swing, JavaFX & SWT 11
M Swing Warum öffnen sich beim Zeichnen mit Swing plötzlich zwei Fenster? AWT, Swing, JavaFX & SWT 5
P ScrollPane nach zeichnen dynamisch resize AWT, Swing, JavaFX & SWT 7
M Swing In GUI-Builder-JFrame mit Menü Schreiben und Zeichnen AWT, Swing, JavaFX & SWT 4
N 2D-Grafik 2 Probleme beim zeichnen AWT, Swing, JavaFX & SWT 18
S Swing Bild auf jPanel nach Änderung von JComboBox zeichnen AWT, Swing, JavaFX & SWT 4
C Funktionen zeichnen AWT, Swing, JavaFX & SWT 16
P JPanel neu zeichnen AWT, Swing, JavaFX & SWT 10
M Auf einem Hintergrundbild zeichnen AWT, Swing, JavaFX & SWT 2
S Eigene JComponent Image zeichnen AWT, Swing, JavaFX & SWT 3
T Oval auf ein JPanel zeichnen AWT, Swing, JavaFX & SWT 3
L Zeichnen in zwei Fenstern AWT, Swing, JavaFX & SWT 8

Ähnliche Java Themen


Oben