Verschiedene Zeichenwerkzeuge

Status
Nicht offen für weitere Antworten.
F

fat32

Gast
Hi,

ich stehe gerade vor dem Problem, dass es in meinem geplanten Programm mehrere Zeichenwerkzeuge geben soll (so wie bei Paint: Stift, Kreis, Rechteck, ...)

Diese Werkzeuge müssen in der Lage sein, das Bild zu manipulieren. Das erste Problem:
Jedes Werkzeug braucht andere Informationen. Manche brauchen die Mausposition, andere die gerade gewählte Farbe, wieder andere brauchen nur das Bild, usw.

Wie mache ich das am besten? Mir fällt nichts besseres ein, als dass ich eine Klasse mache, deren Objekte alle möglichen Informationen aufnehmen kann (Registry) und sich dann die Werkzeuge die benötigten Infos holen. Diese Möglichkeit kommt mir ziemlich unsauber vor.

Dann habe ich noch das Problem, dass bei manchen Funktionen (insb. Kreis und Rechteck) erst entgültig auf das Bild gezeichnet werden soll, wenn ein Dragvorgang beendet ist.
Solange die Maustaste gedrückt ist und die Maus bewegt wird, soll eine "Vorschau" angezeigt werden.

Das letzte Problem ist die Rückgängig-Funktion. Ich könnte das Command-Pattern implementieren und vor jeder Änderung am Bild eine aktuelle version als Kopie ablegen. Das ist aber sehr speicherintensiv. Dafür wäre es realtiv einfach zu realisieren.
Eine andere Möglichkeit wäre es, jeweils nur die geänderten Pixel zu speichern. Aber wie mache ich das bei einem Kreis, den ich per drawArc() gezeichnet habe?

Fragen, Fragen, Fragen...

Ich hoffe, ihr könnt mir ein paar Ideen geben :)

MfG
Simon
 
G

Gast2

Gast
Das erste Problem:
Jedes Werkzeug braucht andere Informationen. Manche brauchen die Mausposition, andere die gerade gewählte Farbe, wieder andere brauchen nur das Bild, usw.
kein Problem
Java:
public abstract class Werkzeug {
    public abstract paintVorschau( [...] );
    public abstract paintReal( [...] );
}

Wie mache ich das am besten? Mir fällt nichts besseres ein, als dass ich eine Klasse mache, deren Objekte alle möglichen Informationen aufnehmen kann (Registry) und sich dann die Werkzeuge die benötigten Infos holen. Diese Möglichkeit kommt mir ziemlich unsauber vor.
mit Vererbung und Polymorphie

Das letzte Problem ist die Rückgängig-Funktion.
Reihenfolge merken wie die Werkzeuge verwendet wurden -> Stack
 

Marco13

Top Contributor
Das schreibt sich so leicht hin. Kann aber tricky sein, wenn man es wirklich mal implementieren will. Besonders das Rückgängigmachen ist schwierig, wenn nach der Operation alles zu einem Haufen Pixeln zusammenfällt...
 
G

Gast2

Gast
Moin,

wenn Du einen Schritt zurück gehst zeichnest Du eben das gesammte Bild nochmal ... bis auf den obersten Pinsel ... dann kannst Du das Ganze mit Pixeln machen ... ich sehe da nicht das Problem ... wobei ich nicht weis ob man durch einen Stack iterieren kann ... evt. wäre da eine andere Datenstruktur besser geeignet
 
F

fat32

Gast
Danke!

Bin schon recht weit gekommen.

Momentan seht es so aus:

DrawingController
Dieser Controller beinhaltet einen Stack (ArrayList), der alle Befehle (Linie, Kreis, Stift, ...) beinhaltet. Der wird dann später für die Rückgängig-Funktion verwendet.

Der DrawingController gibt alle Mausbewegungen an den letzten DrawingCommand (Linie, Kreis, Stift, ...) weiter. Dort wird dann individuell entschieden, was passieren soll.

DrawingCommand
Ein DrawingCommand erhält das aktuelle Bild und bekommt vom DrawingController Mausbewegungen und Klicks mitgeteilt. Bei Bedarf manipuliert er dann das Bild.
Ist der Command beendet, ruft er eine Methode im DrawingController auf, die diesen Controller dazu veranlasst, einen neuen Command desselben Typs zu erstellen.
Dadurch erreiche ich, dass beim Rückgängig-Machen Einzelschritte rückgängig gemacht werden können.

Wie ist diese Vorgehensweise? Gut/Schlecht? Warum?

Kreis zeichnen
Mein Problem ist jetzt aber, dass es manche Funktionen gibt, die erst beim Loslassen der Maus das Bild "entgültig" manipulieren sollen. Ein Beispiel hierfür wäre die Kreismalfunktion. Bei dieser Funktion bestimmt man durch den ersten Klick den Mittelpunkt des Kreises und kann die Maus dann bewegen. Dadurch ändert man den Radius. Lässt man die Maus jetzt los, wird der Kreis erst aufs Bild gemalt.

Aber wie mache ich das? Ich möchte ja, dass man während der Mausbewegung schon sieht, wie groß der Kreis später mal wird.

Ich habe mir überlegt, ein transparentes Bild über mein Hauptbild zu legen und dann darauf zu zeichnen, solange die Maus gedrück ist. Erst wenn die Maus losgelassen wird, soll der Kreis dann vom Transparenten Bild ins richtige Bild kopiert werden.
Nur wie lege ich ein transparentes Bild über ein BufferedImage? Konnte beim Googeln nix finden...

Eine andere Möglichkeit wäre, dass ich am Beginn des Kreis-Zeichnens eine Kopie des aktuellen Zustands anfertige. Diesen Zustand lade ich dann immer wieder, bevor ich die "neue" Vorschau darstelle.
Dürfte aber ziemlich rechenaufwändig sein, oder?

Ich freue mich auf eure Antworten!
 

Grey_M

Aktives Mitglied
Ich habe mal ein ganz simples Malprogramm gemacht.
http://ma-tech.de/site/index.php?option=com_wrapper&view=wrapper&Itemid=6

Sourcecode
http://ma-tech.de/services/mapaintboard/MA Paintboard.zip

Würde ich es nochmal machen, dann würde ich die Zeichenoperationen (z.B: Kreis malen), in einer Liste speichern. Damit kann man dann das mit dem Rückgängig realisieren. Einfach die Operation aus der Liste löschen, die Zeichenfläche zurück setzen und die restlichen Operationen der Liste nacheinander durchführen.

Zumindest siehst du in dem Programm, wie man das mit dem Zeichnen von Rechtecken und Kreisen hinkriegt, denn das funktioniert so wie du es willst.
 
Zuletzt bearbeitet:
F

fat32

Gast
Jo, danke

mein Programm habe ich mittlerweile fertig und abgegeben. (Mit rückgängig)
Sobald es bewertet, stelle ich es auf meinen Blog und hier rein... Würde mich dann freuen, wenn ihr meinen Programmierstil bewerten würdet :)

Ich stelle es jetzt noch nicht rein, weil mein Lehrer das nicht unbedingt im Internet finden sollte ---> 0 Punkte ;)

MfG
Simon

EDIT: Das Programm ist klein, aber fein ;) Nur der Downloadlink ist wohl in die Hose gegangen. Kannst du den Link korrigieren? Mich würde der Code sehr interessieren
 
Zuletzt bearbeitet von einem Moderator:
F

fat32

Gast
Hi,

das mit dem Rückgängig hab ich so gelöst:

Immer, wenn etwas gezeichnet wird, wird ein Objekt einer bestimmten Klasse erstellt. Diese Klassen sind alle von DrawingCommand abgeleitet.

So kann ich die Zeichenschritte bequem in einem Stack ablegen.

Wird nun etwas rückgängig gemacht, entferne ich das letzte Elements des Stacks und lege es auf den redoStack (um es später wiederholen zu können)
Jetzt werden alle verbleibenden Elemente neu gezeichnet, indem die execute-Methode aufgerufen wird.

MfG
Simon
 
Status
Nicht offen für weitere Antworten.

Oben