Zeichenprogramm mit Factory-Pattern

Status
Nicht offen für weitere Antworten.

Sindbad1983

Top Contributor
Hi!

Dieses Mal wartet wieder viel Arbeit auf mich...und sehr schwer noch dazu find ich!
Ich steh momentan noch bei einem vernünftigen konzeptuellen Entwurf, hab aber da schon das ein oder andere Problem:

Hier mal die Angabe meines Beispiels:

Vorweg: Am wichtigsten ist die Implementierung nach dem FABRIK-Pattern!!


Einfaches Zeichenprogramm

Schreiben Sie ein Zeichenprogramm, mit dem einfache Figuren (Rechtecke, Ellipsen und Dreiecke)
gezeichnet werden können.

Das Erscheinungsbild von Figuren, z.B. Linienfarbe, Füllfarbe, Linienart, Liniendicke, … soll sich leicht
ändern lassen. Neue Figuren sollen deshalb durch eine Fabrik erzeugt werden.

In einem Pull-Down Menü sollen sich mindestens 2 verschiedene Erscheinungsbilder umschalten lassen,
die Sie beliebig wählen können. Sie benötigen also 2 Fabrik-Implementierungen, die bei Auswahl eines Menü-Eintrags gewechselt werden. Diese Einstellung wirkt sich nur für neu gezeichnete Figuren aus, bereits bestehende Figuren behalten ihr altes Erscheinungsbild.

Im Zeichenprogramm soll es möglich sein, durch Ziehen mit der Maus Figuren verschieden große Figuren
zu zeichnen. Bei gedrückter Shift-Taste sollen Ellipsen erzeugt werden, bei gedrückter Strg-Taste
Dreiecke, sonst Rechtecke.

Kapseln Sie die Zeichen-Funktionalität in einer eigenen Swing-Komponente. Diese Komponente erzeugt
mit Hilfe einer Fabrik neue Figuren. Achten Sie also darauf, dass die Komponente unabhängig von der Art der Figuren ist.

Implementieren Sie das Beispiel mit einer Fabrik.


Ich hab mir gedacht, ich könnt mal so herangehen:

1. eine abstrakte Klasse Figure mit einer abstrakten Methode paint()
2. 3 Unterklassen Rectangle, Circle, Eplise , die von Figure erben und die paint()-Methode verschieden implementieren
3. Ein Frame, das ein JPanel (die Zeichenfläche selbst) beeinhaltet ->also die GUI
4. eine abstrakte Klasse AbstractFigureFactory
5. 2 Klassen, die von dieser erben: BlackAndWhiteFigureFactory ColoredFigureFactory

denn es sollen figures entweder in Farbe oder in schw-weiß gezeichnet werden können!das sind meine 2 verschiedenen Fabrik-Ausprägungen...
Das soll man ja im Pull-Down-Menü auswählen können!
Je nach Auswahl werden dann die unterschiedlichen figures gezeichnet!


Kann ich das so machen?Hab ich das richtig verstanden?
Oder brauch ich da noch mehr Klassen?
Wer hilft mir bitte bei dem Beispiel?
:bae: :bae: :bae:
 

Sky

Top Contributor
Ich weiß nicht, ob dies dann an der Aufgabenstellung vorbei geht, aber hier noch ein paar Tips:

- circle ist eine spezielle ellipse; könnte man also auch deshalb so ableiten (oder meintest Du eher 'triangle', weils Dreieck noch fehlt...)
- BlackAndWhiteFigureFactory könnte eine spezielle ColoredFigureFactory sein (hier sind dann einfach schon die Farben gesetzt) ODER ColoredFigureFactory könnte BlackAndWhiteFigureFactory erweitern (um die Eigenschaft farben darzustellen)
 

Sindbad1983

Top Contributor
ja stimmt, ich mach statt ellipse ein dreieck

nein, wir müssen BlackAndWhiteFigureFactory und ColordFigureFactory getrennt implementieren...

ich werd jetzt gleich mal anfangen...
 

Sindbad1983

Top Contributor
zusätzlich brauch ich ja noch ein GUI-Element, in dem ich das ganze ja anzeige:

ich hab mir das so gedacht:

ich mach eine eigene Klasse MyPanel, die von JPanel erbt, und die dann meine Zeichenfläche darstellen soll!

Ein meiner Klasse PaintFrame extends Frame erzeug ich dann
MyPanel und füg es dem Frame hinzu!

Ich brauch die 2 unterschiedlichen Klassen, weil bei JFrame muss ich die Menüzeile hinzufügen und bei MyPanel muss ich die Mausereignisse handeln...
sind diese Gedanken richtig?

Oder soll ich das anderes/besser machen?
 

Wildcard

Top Contributor
Grundsätzlich richtig, würde aber statt eines JPanels eine JComponent nehmen, da du ja nur zeichnen willst, und JComponent die Basis Klasse ist...
 

Sindbad1983

Top Contributor
:roll:

was sagt ihr zu meinem Einstieg?
Kann ich mit dem so weitertun?
Oder soll ich da schon was ändern?

Bitte um Kritik:


Code:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;


public class PaintFrame extends JFrame implements ActionListener{
	
	
	Zeichenflaeche zeichenflaeche;
	

	
	public PaintFrame(String titel){
		super(titel);
		
		
		
		
		
		Container c=getContentPane();
		
		zeichenflaeche=new Zeichenflaeche();
	
		c.add(zeichenflaeche);
		
	
		
	}
	
	public void makeMenu(){
		
	MenuBar bar=new MenuBar();
		
		
		 Menu m = new Menu("Look & Feel");
		 m.add(new MenuItem("Rot"));
		 m.add(new MenuItem("Blau"));
		 m.add(new MenuItem("Grün"));
		 bar.add(m);
		 setMenuBar(bar);
		 
		
	
	}
	
	public void actionPerformed(ActionEvent e) {
		
		
	}
	
	public static void main(String [] args){
		PaintFrame frame=new PaintFrame("Zeichenprogramm");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
		frame.setSize(600,600);
		frame.setLocation(300,300);
		frame.setVisible(true);
		frame.makeMenu();
	
		
		
	}

	

}


Code:
public class Zeichenflaeche extends JPanel implements MouseListener, MouseMotionListener, ActionListener{
	
	int pressedX;
	int pressedY;
	int releasedX;
	int releasedY;
	
	
	public Zeichenflaeche(){
		setBackground(Color.RED);
		this.addMouseListener(this);
	}
	

	public void mouseClicked(MouseEvent e) {
		
		
	}

	public void mousePressed(MouseEvent e) {
		
		pressedX=getX();
		pressedY=getY();
		
		
		
		
	}

	public void mouseReleased(MouseEvent e) {
		
		releasedX=getX();
		releasedY=getY();
		repaint();
	
	
		
	}

	public void mouseEntered(MouseEvent e) {
		
		
	}

	public void mouseExited(MouseEvent e) {
		
		
	}

	public void mouseDragged(MouseEvent e) {
	
		
	}

	public void mouseMoved(MouseEvent e) {
		
		
	}

	public void actionPerformed(ActionEvent e) {
		
		
	}
	
}

Code:
public abstract class AbstractFigureFactory {
	
	public abstract Figure createFigure();

}

Code:
public class BlackAndWhiteFigureFactory extends AbstractFigureFactory{

	
	public Figure createFigure() {
		
		
		//return new ?????
		
		
		
		return null;//das stimmt natürlich nicht! 
	}
	


}


und dasselbe bei ColoredFigureFactory..da kenn ich mich jetzt überhaupt nicht mehr aus!
Ich mein, wenn ich es ohne das Fabrik-Pattern implementieren müsste, würd ich glaub ichs schaffen..
aber das verwirrt mich irgendwie..

Was wären die nächsten Schritte?
Danke!!!
 

Sindbad1983

Top Contributor
in dem Beispiel (Handbuch der Programmierung) kommt vor:



Code:
001 /* Listing1014.java */
002 
003 //------------------------------------------------------------------
004 //Abstrakte Produkte
005 //------------------------------------------------------------------
006 abstract class Product1
007 {
008 }
009 
010 abstract class Product2
011 {
012 }
013 
014 //------------------------------------------------------------------
015 //Abstrakte Factory
016 //------------------------------------------------------------------
017 abstract class ProductFactory
018 {
019   public abstract Product1 createProduct1();
020 
021   public abstract Product2 createProduct2();


bei mir gibts eigentlich nur ein Produkt, oder?


denn Rectangle, Circle und Triangle sind alle eine Figure!
Oder????

Also würd bei mir passen:




Code:
public abstract class AbstractFigureFactory{

public abstract Figure createFigure();

}


für mich logischer wäre aber:

Code:
public abstract class AbstractFigureFactory {
	
	public abstract Figure createRectangle();
	public abstract Figure createCircle();
	public abstract Figure createTriangle();

}

Mann, das ist echt verwirrend! :bloed:
 

Sky

Top Contributor
Wenn Du nur eine Methode
Code:
public abstract Figure createFigure();
hast, so brauchst Du doch ein Unterscheidungskriterium, wann welche Figur erzeugt werden soll, d.h. Du brauchst noch einen Parameter:

z.B.
Code:
public abstract Figure createFigure(int type);
oder
Code:
public abstract Figure createFigure(String type);
 

Sindbad1983

Top Contributor
was ist, wenn ich es so mache??

geht das auch??


Code:
public abstract class AbstractFigureFactory {
	
	public abstract Figure createRectangle();
	public abstract Figure createCircle();
	public abstract Figure createTriangle();
	
}


Code:
public class BlackAndWhiteFigureFactory extends AbstractFigureFactory{

	
	public Figure createRectangle() {
		
		return new Rectangle();
	}

	
	public Figure createCircle() {
		
		return new Circle();
	}

	
	public Figure createTriangle() {
	
		return new Triangle();
	}
	
	
	
}

müsste auch funktionieren, oder?
 
B

Beni

Gast
Normalerweise macht man mehrere Factories: eine für Rechtecke, eine für Kreise... Die sammelt man dann irgendwo in einer Liste, und lässt den Benutzer eine Factory wählen. Das hat den Vorteil, dass man ganz leicht neue Figuren (und ihre Factories) hinzufügen kann, ohne irgendwo seltsame Konstanten zu ändern.
 

Sindbad1983

Top Contributor
ja...ich weiß, so wärs auch nicht soooo schwer, aber wir müssen es so machen:

mit einer Klasse BlackAndWhiteFactory, die nur farblose figures zeichnet
und eine Klasse ColoredFactory, die färbige figures zeichnet!
Und die Farbe soll man über die Menüleiste einstellen können!


Das bringt mich komplett durcheinander! :cry: :cry: :cry:

Ich kann mir das grad überhaupt nicht vorstellen! :autsch:
 

Sindbad1983

Top Contributor
ich lass jetzt das mit den Farben weg, und vereinfach das somit erstmal ein bisschen!

Ich machs jetzt so, wies Beni mir empfohlen hat!


Ich hab eine AbstractFactory und 3 Unterklassen: RectangleFactory, CircleFact......
 

Sky

Top Contributor
Beni hat gesagt.:
Normalerweise macht man mehrere Factories: eine für Rechtecke, eine für Kreise... Die sammelt man dann irgendwo in einer Liste, und lässt den Benutzer eine Factory wählen. Das hat den Vorteil, dass man ganz leicht neue Figuren (und ihre Factories) hinzufügen kann, ohne irgendwo seltsame Konstanten zu ändern.

Nun erschließt sich mir nicht mehr ganz der Mehrwert einer Factory, wenn ich genau eine Factory für eine Figure habe... dann kann ich mir auch ein Interface Figure erstellen und drei Klassen für Kreis, Dreieck und Rechteck, welche das Interface implementieren.
Meines Erachtens sollte es für diese Problemstellung eine Factory geben, welche entweder über einen Parameter oder mittels verschiedener Methoden (createCircle, createRectangle... ) die Frigure liefern.
 

Sindbad1983

Top Contributor
naja, ich habs jetzt so probiert: geht aber leider nicht!

er wirft mir ne NullPointerException:


ich such schon wieder seit 2 Stunden den fehler, komm aber nicht drauf

ich versteh das nicht: da programmier ich letzte Woche einen Email-Client und dann hab ich diese Woche massive Probleme mit dynamischer Bindung! :cry: :cry:

Vielleicht kann mir jemand einen Tipp :bae: geben!

Hier nur ein Auszug der wichtigsten Klassen:



Code:
import java.awt.*;
import javax.swing.*;


public abstract class Figure extends JComponent {
	
	int pressedX;
	int pressedY;
	int releasedX;
	int releasedY;
	
	public void getpressedXY(int x, int y){
		pressedX=x;
		pressedY=y;
	}
	
	public void getreleasedXY(int x, int y){
		releasedX=x;
		releasedY=y;
	}

	public abstract void paint(Graphics g);

}

Code:
import java.awt.*;
import javax.swing.*;


public class Rectangle extends Figure{
	

	
	public void paint(Graphics g) {
		g.setColor(Color.blue);
		g.fillRect(pressedX,pressedY,releasedX-pressedX,releasedY-pressedY);
	}
}

Klasse Circle und Triangle genauso nur mit anderer paint-Methode!


Code:
public class PaintFrame extends JFrame implements ActionListener{
	
	
	Zeichenflaeche zeichenflaeche;
	AbstractFigureFactory factory;
	
	public PaintFrame(String titel){
		super(titel);
		
		Container c=getContentPane();
		zeichenflaeche=new Zeichenflaeche(factory);
		c.add(zeichenflaeche);
	}
	
	public void makeMenu(){
		
	MenuBar bar=new MenuBar();
		
		
		 Menu m = new Menu("Look & Feel");
		 m.add(new MenuItem("Rot"));
		 m.add(new MenuItem("Blau"));
		 m.add(new MenuItem("Grün"));
		 bar.add(m);
		 setMenuBar(bar);
	}
	
	public void actionPerformed(ActionEvent e) {
	}
	
	public static void main(String [] args){
		PaintFrame frame=new PaintFrame("Zeichenprogramm");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
		frame.setSize(600,600);
		frame.setLocation(300,300);
		frame.setVisible(true);
		frame.makeMenu();
			
	}

}

Code:
public class Zeichenflaeche extends JPanel implements MouseListener, MouseMotionListener,  KeyListener{
	
	AbstractFigureFactory factory;
	Figure figure;
	Graphics g;
	
	int pressedX;
	int pressedY;
	int releasedX;
	int releasedY;
	
	
	public Zeichenflaeche(AbstractFigureFactory factory){
		factory=factory;
		setBackground(Color.RED);
		this.addMouseListener(this);
		this.addMouseMotionListener(this);
		this.addKeyListener(this);
	}
	
	public Figure makeFigure(){
		Figure figure=factory.createFigure();
		
		figure.paint(g);
		return figure;
	}
	

	public void mouseClicked(MouseEvent e) {	
	}

	public void mousePressed(MouseEvent e) {
		
		pressedX=getX();
		pressedY=getY();
		figure.getpressedXY(pressedX,pressedY);
		
	}

	public void mouseReleased(MouseEvent e) {
		
		releasedX=getX();
		releasedY=getY();
		figure.getreleasedXY(releasedX,releasedY);
		repaint();

	}

	public void mouseEntered(MouseEvent e) {
	}

	public void mouseExited(MouseEvent e) {
	}

	public void mouseDragged(MouseEvent e) {
	}

	public void mouseMoved(MouseEvent e) {
	}

	

	public void keyTyped(KeyEvent e) {
		 char key = e.getKeyChar();
			
			if(key==KeyEvent.VK_ENTER){
				factory=new RectangleFactory();
			}
			else if(key==KeyEvent.VK_SPACE){
				factory=new CircleFactory();
			}else{
				factory=new TriangleFactory();
			
			}
		
	}

	public void keyPressed(KeyEvent e) {
	}
		
	public void keyReleased(KeyEvent e) {	
	}
	
}

Code:
public abstract class AbstractFigureFactory {
	
	public abstract Figure createFigure();
	
}

Code:
public class RectangleFactory extends AbstractFigureFactory{

	
	public Figure createFigure() {
		
		return new Rectangle();
	}
}

die anderen beiden genauso!
 

Wildcard

Top Contributor
Code:
factory=factory;
das bringt nichts! muss heißen:
Code:
this.factory=factory;
 

Sindbad1983

Top Contributor
ich hab diese Methode noch verändert:

Code:
public void keyTyped(KeyEvent e) {
		 char key = e.getKeyChar();
			
			if(key==KeyEvent.VK_ENTER){
				factory=new RectangleFactory();
				Zeichenflaeche flaeche=new Zeichenflaeche(factory);
				Figure figure=flaeche.makeFigure();
			}
			else if(key==KeyEvent.VK_SPACE){
				factory=new CircleFactory();
				Zeichenflaeche flaeche=new Zeichenflaeche(factory);
				Figure figure=flaeche.makeFigure();
			}else{
				factory=new TriangleFactory();
				Zeichenflaeche flaeche=new Zeichenflaeche(factory);
				Figure figure=flaeche.makeFigure();
			
			}
		
	}


naja...geht aber auch nicht!

Sobald ich auf die Fläche klicke, kommen viiiiiiiele Exceptions ! :cry:

Mann..sowas ist echt frustrierend!
 

Wildcard

Top Contributor
hast du das geändert? Wo kommen die Exceptions genau? Dann muss ich nicht so viel suchen :wink:
 

Sindbad1983

Top Contributor
ja das hab ich schon eingefügt!

Sobald ich auf die Zeichenfläche klicke, kommt im Ausgabefenster folgendes:


Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at figures.Zeichenflaeche.mousePressed(Zeichenflaeche.java:52)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)


Danke, dass du mir hilfst!

das ganze sagt mir eher wenig!

Ich weiß nämlich schon wieder nicht mehr weiter bzw. was ich noch ändern könnte! :###

wie lange programmíerst du schon?
 
S

stev.glasow

Gast
Sindbad1983 hat gesagt.:
Code:
public void keyTyped(KeyEvent e) {
		 char key = e.getKeyChar();
			
			if(key==KeyEvent.VK_ENTER){
				factory=new RectangleFactory();
				Zeichenflaeche flaeche=new Zeichenflaeche(factory);
				Figure figure=flaeche.makeFigure();
			}
			else if(key==KeyEvent.VK_SPACE){
				factory=new CircleFactory();
				Zeichenflaeche flaeche=new Zeichenflaeche(factory);
				Figure figure=flaeche.makeFigure();
			}else{
				factory=new TriangleFactory();
				Zeichenflaeche flaeche=new Zeichenflaeche(factory);
				Figure figure=flaeche.makeFigure();
			
			}
		
	}

Was soll das eigentlich bringen, bis auf 'factory' sind alle Varablen lokal.
 
B

Beni

Gast
sky80 hat gesagt.:
Beni hat gesagt.:
Normalerweise macht man mehrere Factories: eine für Rechtecke, eine für Kreise... Die sammelt man dann irgendwo in einer Liste, und lässt den Benutzer eine Factory wählen. Das hat den Vorteil, dass man ganz leicht neue Figuren (und ihre Factories) hinzufügen kann, ohne irgendwo seltsame Konstanten zu ändern.

Nun erschließt sich mir nicht mehr ganz der Mehrwert einer Factory, wenn ich genau eine Factory für eine Figure habe... dann kann ich mir auch ein Interface Figure erstellen und drei Klassen für Kreis, Dreieck und Rechteck, welche das Interface implementieren.
Meines Erachtens sollte es für diese Problemstellung eine Factory geben, welche entweder über einen Parameter oder mittels verschiedener Methoden (createCircle, createRectangle... ) die Frigure liefern.
Und wie erstellst du dann einen neuen Kreis, wenn du keine Factory hast :bahnhof: ? Mit einem fest einkodierten "new Circle" hast du verloren, weil alles dynamische weg ist.
 

Wildcard

Top Contributor
figure ist null.
Wie stevg schon geschrieben hat erstellst du immer lokale Variablen anstatt auf die Instanz-Variablen zuzugreifen.
also statt
Code:
 Figure figure=factory.createFigure();
Code:
figure=factory.createFigure();
aber wieso hat Zeichenfläche überhaupt eine Instanzvariable figure? Das heißt ja das es auf der Zeichenfläche nur eine Figure gibt? :bahnhof:
 

Sindbad1983

Top Contributor
wenn z.B. die Enter-Taste gedrückt wird, dann ein RectangleFactory-Object erzeugt werden->dieses übergib ich dann der Zeichenfläche und ruf mit dieser die makeFigure()-Methode auf..diese gibt eine Figur zurück

so sollte es zumindest sein...oder auch nicht...das ist ja mein Problem, dass ich selber nicht weiß, wie das genau geht.. :cry:

habs nur mal so probiert
 
S

stev.glasow

Gast
Weißt du was der Unterschied zwischen lokalen Variablen und Instanz-Variablen ist?
 

Wildcard

Top Contributor
Sindbad1983 hat gesagt.:
wenn z.B. die Enter-Taste gedrückt wird, dann ein RectangleFactory-Object erzeugt werden
das heißt du erzeugst wenn du eine Figure erstellen willst eine neue Factory???
Deine Factorys sollte es eigentlich nur einmal geben. Die Factory an die Zeichenfläche zu übergeben ist auch ziemlich seltsam.
Die Zeichenfläche sollte nur die figure bekommen die die Factory erzeugt hat, und nicht die Factory selbst...
 

Sindbad1983

Top Contributor
naja..

Instanzvariablen sind Variablen, die man in der Klasse deklariert ->diese sind dann die "Daten" der erzeugten Objekte ->und mit Hilfe von Methoden kann man die Werte der Variablen verändern bzw. hat Zugriff darauf!

Lokale Variablen sind nur in einem Block sichtbar..naja aber mehr weiß ich da schon nicht mehr drüber!
Man kann auf Lokale Variablen nicht zugreifen, weil sie ja nicht sichtbar sind von außen!
Außer mit Hilfe von Methoden!

Auf Instanzvariablen hingegen ist Zugriff möglich, außer sie sind private!
Stimmt das so?
 
S

stev.glasow

Gast
jor stimmt soweit, außer das mit dem private, aber ist hier für egal.

Aber ich verstehe dann nicht warum du diese lokal machst:
Zeichenflaeche flaeche=new Zeichenflaeche(factory);
Figure figure=flaeche.makeFigure();
diese existieren so doch nur n dem Block.
 

Sindbad1983

Top Contributor
naja hast eigentlich Recht!



Code:
public Zeichenflaeche(){
		
		setBackground(Color.RED);
		this.addMouseListener(this);
		this.addMouseMotionListener(this);
		this.addKeyListener(this);
	}
	
	public Figure makeFigure(){
		Figure figure=factory.createFigure(); //eventuell Figure weg!
		
		figure.paint(g);
		return figure;
	}

                    .
                    .
                    .
  

	public void keyTyped(KeyEvent e) {
		 char key = e.getKeyChar();
			
			if(key==KeyEvent.VK_ENTER){
				factory=new RectangleFactory();
				Zeichenflaeche flaeche=new Zeichenflaeche();
				figure=flaeche.makeFigure();
			}
			else if(key==KeyEvent.VK_SPACE){
				factory=new CircleFactory();
				Zeichenflaeche flaeche=new Zeichenflaeche();
				figure=flaeche.makeFigure();
			}else{
				factory=new TriangleFactory();
				Zeichenflaeche flaeche=new Zeichenflaeche();
				figure=flaeche.makeFigure();
			
			}
		
	}

aber so stimmts ja auch nicht, oder?

außerdem:

ich muss zu Beginn der Klasse Figure figure deklarieren, weil ich sonst ja bei

Code:
public void mousePressed(MouseEvent e) {
		
		pressedX=getX();
		pressedY=getY();
		figure.getpressedXY(pressedX,pressedY);
		
	}

keinen Zugriff mehr hätte oder?
 

Sindbad1983

Top Contributor
boa, jetzt verzweifle ich gleich:

Zeichenflaeche flaeche=new Zeichenflaeche() ist ja auch falsch!
Das darf ich auch nicht lokal machen

mir fehlt da jetzt absolut der Durchblick! :cry: :cry: :cry:
 

Sindbad1983

Top Contributor
also nochmal zur Verständnis:


wenn ich

Figure figure;

als Instanzvariable deklarier, dann heißt das, dass ich eine Figure-Variable hab mit den Instanzvariablen von Figure(also pressedX, pressedY etc)
D.h. ich kann maximal eine Figur in Zeichenflaeche speichern?
->das würd ich eigentlich nicht wollen!
Stimmt das so?
 
B

Beni

Gast
Wenn du eine Instanzvariable hast, bedeutet dies, dass pro Zeichenfläche nur eine Figure existiert (bzw, angezeigt wird).

Das ist ein bisschen unglücklich, deshalb würde ich diese Figuren in einer Liste sammeln.

Code:
List figures = new ArrayList();
figures.add( ... );

Siehe hier.
 

Sindbad1983

Top Contributor
ja ist vielleicht ne gute Idee..
ich werds morgen mit einer Liste probiern!

aber ich sag mal, das wird nicht das zentrale Problem sein!

Denn es kann ja bis dato nicht mal 1 Figur gezeichnet werden!
Und das Problem kann nur in der Klasse Zeichenflaeche liegen, denk ich mir mal!

Naja..vielleicht kann mir ja trotzdem noch jemand einen Hinweis in Richtung Lösung geben!
Gute Nacht!

Danke für eure Hilfe!
ciao, bis morgen
 

Sky

Top Contributor
Beni hat gesagt.:
sky80 hat gesagt.:
Beni hat gesagt.:
Normalerweise macht man mehrere Factories: eine für Rechtecke, eine für Kreise... Die sammelt man dann irgendwo in einer Liste, und lässt den Benutzer eine Factory wählen. Das hat den Vorteil, dass man ganz leicht neue Figuren (und ihre Factories) hinzufügen kann, ohne irgendwo seltsame Konstanten zu ändern.

Nun erschließt sich mir nicht mehr ganz der Mehrwert einer Factory, wenn ich genau eine Factory für eine Figure habe... dann kann ich mir auch ein Interface Figure erstellen und drei Klassen für Kreis, Dreieck und Rechteck, welche das Interface implementieren.
Meines Erachtens sollte es für diese Problemstellung eine Factory geben, welche entweder über einen Parameter oder mittels verschiedener Methoden (createCircle, createRectangle... ) die Frigure liefern.
Und wie erstellst du dann einen neuen Kreis, wenn du keine Factory hast :bahnhof: ? Mit einem fest einkodierten "new Circle" hast du verloren, weil alles dynamische weg ist.

Also, ich habe mir die FAQ noch einmal durchgelesen, und dort steht zum Factory-Pattern folgendes Beispiel:
Code:
public class Foo {
  Foo() { //Konstruktor nur für package zugänglich, da factory Methode in andere Klasse im selben Package liegt
  }
}

public class Bar {
  Bar() { //Konstruktor nur für package zugänglich, da factory Methode in andere Klasse im selben Package liegt
  }
}

public class FooBarFactory {
  public static Foo getFoo( Settings s ) { //Factory - Methode für Foo
    Foo f = new Foo(); //erlaubt
    //intialisiere f
    return f;
  }

  public static Bar getBar( Settings s ) { //Factory - Methode für Bar
    Bar b = new Bar(); //erlaubt
    //intialisiere b
    return b;
  }
}

Wenn ich dies nun auf das Sindbad's Problem beziehe, so würde meine Interpretation so aussehen:
Code:
class Rectangle extends Figure {
  Rectangle() { //Konstruktor nur für package zugänglich, da factory Methode in andere Klasse im selben Package liegt
  }
  // getter und setter
}

class Circle extends Figure {
  Circle() { //Konstruktor nur für package zugänglich, da factory Methode in andere Klasse im selben Package liegt
  }
  // getter und setter
}

class FigureFactory {
  // Rückgabewert könnte natürlich auch Rectangle sein
  public static Figure getRectangle( Settings s ) { //Factory - Methode für Foo
    Rectangle r = new Rectangle(); //erlaubt
    //intialisiere r
    return r;
  }

  // Rückgabewert könnte natürlich auch Circle sein
  public static Figure getCircle( Settings s ) { //Factory - Methode für Bar
    Circle c = new Circle(); //erlaubt
    //intialisiere c
    return c;
  }
}
 

Sindbad1983

Top Contributor
naja...aber das hab ich eh im Grund auch oder?

ich hab halt nur statt einer FigureFactory eine abstrake Klasse mit 3 Unterklassen...

also ich glaub von der Konzeption müsste es schon stimmen
 

Sindbad1983

Top Contributor
So, ich hab jetzt die beiden Klassen PaintFrame und Zeichenflaeche nochmals verändert, und ich glaube ich bin jetzt noch näher an einer möglichen Lösung!

Es wirft mir zumindest keine Exception mehr!

außerdem übergib ich nicht mehr der Zeichenflaeche die AbstractFigureFactory, sondern nur mehr der makeFigure-Methode!

Ich möcht jetzt einfach nur mal, dass er 1 Figur (z.B. ein Rechteck zeichnet)..das wär ein Traum!

Leider zeichnet er aber nichts!


Ich bin jetzt echt am Ende mit meinem Latein! :cry:

Ich wüsst auch nicht mehr, wo ich noch nachschaun könnt, bzw. was ich ändern könnte! :roll:


Code:
public class PaintFrame extends JFrame implements ActionListener{
	
	
	
	
	public PaintFrame(String titel){
		super(titel);
		
		Container c=getContentPane();
		Zeichenflaeche zeichenflaeche=new Zeichenflaeche();
		c.add(zeichenflaeche);
	}
	
	
	public void makeMenu(){
		
	MenuBar bar=new MenuBar();
		
		
		 Menu m = new Menu("Look & Feel");
		 m.add(new MenuItem("Rot"));
		 m.add(new MenuItem("Blau"));
		 m.add(new MenuItem("Grün"));
		 bar.add(m);
		 setMenuBar(bar);
		 
		
	
	}
	
	public void actionPerformed(ActionEvent e) {
		
		
	}
	
	public static void main(String [] args){
		PaintFrame frame=new PaintFrame("Zeichenprogramm");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
		frame.setSize(600,600);
		frame.setLocation(300,300);
		frame.setVisible(true);
		frame.makeMenu();
			
	}

}


Code:
public class Zeichenflaeche extends JPanel implements MouseListener, MouseMotionListener,  KeyListener{
	
	Figure figure;
	Graphics g;
	
	int pressedX;
	int pressedY;
	int releasedX;
	int releasedY;
	
	
	public Zeichenflaeche(){
	
		
		setBackground(Color.RED);
		this.addMouseListener(this);
		this.addMouseMotionListener(this);
		this.addKeyListener(this);
		
		//ArrayList list=new ArrayList(); für mehrere Figuren...jetzt soll erstmal 1 Figure gezeichnet werden
	}
	
	public Figure makeFigure(AbstractFigureFactory factory){
		Figure figure=factory.createFigure(); 
		
		figure.paint(g);
		return figure;
	}
	

	public void mouseClicked(MouseEvent e) {
		
		
	}

	public void mousePressed(MouseEvent e) {
		
		pressedX=getX();
		pressedY=getY();
		figure.getpressedXY(pressedX,pressedY);
		
	}

	public void mouseReleased(MouseEvent e) {
		
		releasedX=getX();
		releasedY=getY();
		figure.getreleasedXY(releasedX,releasedY);
		repaint();

	}

	public void mouseEntered(MouseEvent e) {
	}

	public void mouseExited(MouseEvent e) {
	}

	public void mouseDragged(MouseEvent e) {
	}

	public void mouseMoved(MouseEvent e) {
	}

	

	public void keyTyped(KeyEvent e) {
		 char key = e.getKeyChar();
		 
		 AbstractFigureFactory factory;
			
			if(key==KeyEvent.VK_ENTER){
				factory=new RectangleFactory();
				
			}
			else if(key==KeyEvent.VK_SPACE){
				factory=new CircleFactory();
				
				
			}else{
				factory=new TriangleFactory();
				
			
			}
			
			Zeichenflaeche flaeche=new Zeichenflaeche();
			
			Figure figure=flaeche.makeFigure(factory);
		
		
	}

	public void keyPressed(KeyEvent e) {
	}
		
	public void keyReleased(KeyEvent e) {	
	}
	
}


DANKE!
 

Sindbad1983

Top Contributor
maa,ich hoffe echt, dass mir da heut noch wer hilft...
sonst seh ich schwarz..
das Beispiel beinhaltet nämlich sehr viel Wichtiges! ;-(
 

Wildcard

Top Contributor
:autsch:
Diese beiden sind immer null. Was machst du damit?
Code:
   Figure figure;
   Graphics g;

Falls ich du dich jetzt doch entschlossen hast aus den Figures JComponents zu machen, dann muss dir auch klar sein das du
sie wie ganz normale Komponenten auf ein Panel adden musst um sie sehen zu können.
Ich rate dir weiterhin dazu nicht von JComponent zu erben und ein Graphics-Objekt durchzureichen...
Code:
         if(key==KeyEvent.VK_ENTER){
            factory=new RectangleFactory();
            
         }
         else if(key==KeyEvent.VK_SPACE){
            factory=new CircleFactory();
            
            
         }else{
            factory=new TriangleFactory();
Factorys werden nicht mal eben auf Knopfdruck erstellt. Sie existieren nur 1mal!
An dieser Stelle solltest du sie schon gar nicht instanzieren, weil deine Zeichenfläche absolut gar nichts mit der Factory zu tun hat.
Eine Zeichenfläche kriegt Figuren die sie darstellen soll und hat weder mit deren Instanzierung zu tun, noch 'kennt' sie die Factory.
Setz dich mal in Ruhe hin, mach ein vernünftiges Klassendesign, mach dir Gedanken wie du das Zeichnen realisieren willst etc.
 

Sindbad1983

Top Contributor
ja da wirst Recht haben...ich glaub, dass da doch noch einiges falsch ist!
Mir dürfte das mit den Refernzen doch irgendwie noch immer nicht restlos klar sein.. :cry:


Ich hab jetzt mal das Beispiel total vereinfacht, nur mit einer Klasse Rechteck, dem Frame und dem Panel!


Damit ich das mal im ganz Kleinen durchspielen kann und alles versteh, was da so passiert!

Er wirft zwar keine Exceptions, aber zeichnen tut er auch nichts!

Ich versteh das einfach nicht! :oops:
Ich find da nie den Fehler!


Code:
public class Rectangle extends JComponent{
	
	
	

	int pressedX;
	int pressedY;
	int releasedX;
	int releasedY;
	
	public void getpressedXY(int x, int y){
		pressedX=x;
		pressedY=y;
	}
	
	public void getreleasedXY(int x, int y){
		releasedX=x;
		releasedY=y;
	}
	


	public void paint(Graphics g) {
		g.setColor(Color.blue);
		g.fillRect(pressedX,pressedY,releasedX-pressedX,releasedY-pressedY);

	}
     

}

Code:
public class PaintFrame extends JFrame implements ActionListener{
	
	
	
	
	public PaintFrame(String titel){
		super(titel);
		
		Container c=getContentPane();
		Zeichenflaeche zeichenflaeche=new Zeichenflaeche();
		c.add(zeichenflaeche);
		System.out.println("bbbb");
	}
	
	
	public void makeMenu(){
		
	MenuBar bar=new MenuBar();
		
		
		 Menu m = new Menu("Look & Feel");
		 m.add(new MenuItem("Rot"));
		 m.add(new MenuItem("Blau"));
		 m.add(new MenuItem("Grün"));
		 bar.add(m);
		 setMenuBar(bar);
		 System.out.println("ccc");
		 
		
	
	}
	
	public void actionPerformed(ActionEvent e) {
		
		
	}
	
	public static void main(String [] args){
		PaintFrame frame=new PaintFrame("Zeichenprogramm");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
		frame.setSize(600,600);
		frame.setLocation(300,300);
		frame.setVisible(true);
		frame.makeMenu();
			
	}

}

Code:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;

import javax.swing.*;


public class Zeichenflaeche extends JPanel implements MouseListener, MouseMotionListener{
	
	
	Graphics g=getGraphics();
	
	Rectangle r;
	
	
	int pressedX;
	int pressedY;
	int releasedX;
	int releasedY;
	
	
	
	
	
	public Zeichenflaeche(){
		
		System.out.println("eee");
	
		
		setBackground(Color.RED);
		this.addMouseListener(this);
		this.addMouseMotionListener(this);
		
		
		System.out.println("ddd");
		
	
	}
	
	
	

	public void mouseClicked(MouseEvent e) {
		
		
	}

	public void mousePressed(MouseEvent e) {
		
		r=new Rectangle(); //das weiß ich nicht, ob stimmt...ich muss ja aber ein Rechteck irgendwo erzeugen, sonst bekomm ich ne NullPointerException
		
		System.out.println("aaaaa");
		this.pressedX=getX();
		this.pressedY=getY();
	
		r.getpressedXY(pressedX,pressedY);
		System.out.println("zzzz");
	
		
		
	}

	public void mouseReleased(MouseEvent e) {
		
		System.out.println("yyyyy");
		this.releasedX=getX();
		this.releasedY=getY();
		r.getreleasedXY(releasedX,releasedY);
		repaint();
		
		System.out.println("ffff");

	}

	public void mouseEntered(MouseEvent e) {
	}

	public void mouseExited(MouseEvent e) {
	}

	public void mouseDragged(MouseEvent e) {
	}

	public void mouseMoved(MouseEvent e) {
	}

	
	
}


ich hab oben eine Instanzvariable Rectangle r;

wenn ich dann sag:

Code:
r.getpressedXY(pressedX,pressedY);

dann müsste er eigentlich den x und y -Wert im Rechteck setzen oder?
 

Wildcard

Top Contributor
1) deine Methoden sind falsch benannt. 'get' bedeutet IMMER das du etwas zurückbekommst (auch auf die Kamelschreibweise achten) alles andere wird völlig verwirrend!
2) anstatt mit getX, getY zu arbeiten gehts viel einfach wenn du gleich getClickPoint verwendest.
3) Nenn deine Klasse nicht Rectangle weils diese Klasse schon gibt!
3)Wie gesagt, wenn du Rectangle von JComponent ableitest dann musst du diese Komponente eben genau wie ein JLabel deinem Panel hinzufügen, sonst wirst du da nie was sehen...
 

Sindbad1983

Top Contributor
ja aber wie hinzufügen?

normalerweise sag ich:

Code:
JPanel p=new JPanel();

JButton b=new JButton("B");

p.add(b);


aber das geht da nicht so einfach...
ich hätts im Konstruktor versucht, aber das funktioniert auch nicht...

Code:
add(r);
 

Wildcard

Top Contributor
doch genau so:
Code:
add(r);
vorher allerdings die Bounds setzen da du sonst wenig sehen wirst.
 

Sindbad1983

Top Contributor
Leider....geht nicht!
Ich verstehs nicht!
Ich müsst doch jetzt eigentlich an alles gedacht haben..




Code:
public class Zeichenflaeche extends JPanel implements MouseListener, MouseMotionListener{
	
	
	Graphics g=getGraphics();
	
	
	Rectangle r;
	
	
	int pressedX;
	int pressedY;
	int releasedX;
	int releasedY;
	
	public Zeichenflaeche(){
		
		System.out.println("eee");
		setBounds(0,0,600,600);
	
		
		setBackground(Color.RED);
		this.addMouseListener(this);
		this.addMouseMotionListener(this);
		System.out.println("ddd");
	}
	
	
	

	public void mouseClicked(MouseEvent e) {
		
		
	}

	public void mousePressed(MouseEvent e) {
		
		r=new Rectangle();
		add(r);
		
		
		System.out.println("aaaaa");
		this.pressedX=getX();
		this.pressedY=getY();
	
		r.getpressedXY(pressedX,pressedY);
		System.out.println("zzzz");
	
		
		
	}

	public void mouseReleased(MouseEvent e) {
		
		System.out.println("yyyyy");
		this.releasedX=getX();
		this.releasedY=getY();
		r.getreleasedXY(releasedX,releasedY);
		repaint();
		
		System.out.println("ffff");

	}

	public void mouseEntered(MouseEvent e) {
	}

	public void mouseExited(MouseEvent e) {
	}

	public void mouseDragged(MouseEvent e) {
	}

	public void mouseMoved(MouseEvent e) {
	}

	
	
}
 

Wildcard

Top Contributor
Nein! setBounds auch auf r aufrufen!
Denk auch dran das jede JComponent ihr eigenes Koordinatensystem hat, und du deshalb bei 0,0 anfangen musst zu zeichnen!
 

Sindbad1983

Top Contributor
tut mir leid...es geht nicht!

es muß für jede Komponente die genaue Position definiert werden, sowie die Breite und die Höhe!Die werden für jede Komponente über die Methode setBounds() festgelegt.

aber das Rechteck verändert ja immer seine Position...

ich hab so gemacht:



Code:
r.setBounds(pressedX,pressedY,releasedX,releasedY);

und eben noch bei der Zeichenfläche:

Code:
setBounds(0,0,600,600);
 

Wildcard

Top Contributor
Code:
setBound(int x, int y, int width, int heigth);

Code:
r.setBounds(pressedX,pressedY,releasedX,releasedY);
nicht ganz das selbe :wink:

Wildcard hat gesagt.:
Denk auch dran das jede JComponent ihr eigenes Koordinatensystem hat, und du deshalb bei 0,0 anfangen musst zu zeichnen!
hast du das auch schon geändert?
 

Sindbad1983

Top Contributor
du meinst wohl setBounds(int x, int y...etc) oder?

weil bei setBound gibts nur setBound(true) !?!

und:

Denk auch dran das jede JComponent ihr eigenes Koordinatensystem hat,

das versteh ich nicht


hab eh setBounds(0,0,....) gemacht!

Oder ist das was anderes?
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Oben