# [Graphics] Flächen füllen?



## Norbertus (30. September 2009)

Hallo liebe User,

ich habe ein kleines Problem, da ich einfach nicht mehr weiterkomme :-(
Ich habe in Java ein kleines Malprogramm geschrieben, wo man ein wenig rum malen kann.

Das mache ich, in dem ich einfach über drawRect mit 5 Pixeln Abstand einen größeren Pinsel simuliere, in verschiedenen Farben. So, und nun habe ich eine Sache die ich gerne einbauen würde: Genau wie in Paint, kann man dort Flächen füllen - Also ich male mit meinen Rechtecken einen Kreis, und würde diesen gerne dann füllen.

Ich hab schon viel im Internet gesucht, aber bisher nicht verstanden wie das funktionieren sollte. Es wäre super, wenn jemand eine Idee hätte. Danke


----------



## freakxnet (30. September 2009)

Also ich bin da jetzt in dem grafischen Breich auch kein Profi aber meiner Meinung nach müsstest du, wenn ich dich richtig verstanden habe das du z.b. ein Rechteck mit einer Farbe in seinen Grenzen ausfüllen möchtest, dir das Pixel hernehmen wo du auf "Füllen" gedrückt hast. Ich habe das auch noch nicht gemacht aber ich könnte es mir so vorstellen.

1) Farbe die unter dem Pixel ist Speichern das ist quasi deine Farbe die du ja ersetzen möchtest. 

2) Jetzt gehst du von der Position aus in x- und dann x+ position und fischt dir die Farben raus die du findest. Das könnte man als "Grenzfarben" verwenden.

3) Jetzt hast du erstmal die Informationen die du bräuchtest um aufzufüllen.

4) Schleifen um den Punkt drumm herum bauen und von der Position aus in y-,  x-  und dann auf der selben y Position in x+ und dann das ganze noch für y+. 

5) Jedes mal wenn du dann auf deine Farbe triffst die du ersetzen möchtest malst du dein Pixel oben drüber und sobald du deine Randfarbe erreichst brichst du ab und machst mit der nächsten Richtung weiter.

Wenn dann alles geklappt hat sollte eigentlich dein zu füllender Bereich mit der neuen Farbe erscheinen. Wie gesagt ich habs noch nicht gemacht. Aber so in der Art würde ich es probieren.

MFG freakxnet


----------



## Norbertus (1. Oktober 2009)

Vom Ansatz klingt das soweit Interessant, muss ich einmal probieren - Klingt natürlich erstmal nicht sehr performant, aber das täuscht auch öfters mal.

Ich hab gestern probiert über GeneralPath jeder Linie als Path zu speichern, aber so richtig "füllen" wie in Paint kann ich damit auch nicht. Cruzifix ist das :-D


----------



## Norbertus (6. Oktober 2009)

Also das Füllen hat super geklappt mit einem eigenen Algorithmus und dem Einsatz eines BufferedImage.

Nun habe ich noch eine Frage, wo ich an der Logik ein wenig hänge. Gibt es eine einfache Möglichkeit die Funktionen "Schritt  zurück" einzubauen?


----------



## DosCoder (6. Oktober 2009)

Hi, 
dazu musst du jeden Malschritt dokumentieren, beispielsweise in einer ArrayList. 
Dazu kannst du sogenannte Command-Klassen programmieren, also:

```
public class DrawLineCommand extends Command(

    private int x1,y1,x2,y2;

    public DrawLineCommand(int x1, int x2, int y1, int y2){
       //Zuweisungcode einfügen
    }

   public void execute(Graphics g){
       g.drawLine(x1,y1,x2,y2);
   }

}
```

So kannst du alle deine Draw-Befehle implentieren, du musst nur noch eine abstrakte Klasse Command programmieren, die die Methode execute(Graphics g) enthält.

Je nach deinem Algorithmus mussst du jetzt jede Aktion in dieser ArrayList<Command> speichern, sie in der paintComponent-Methode durchlaufen und jeden Befehl ausführen:

```
@Override public void paintComponent(Graphics g){
    for(Command c: commands){
      c.execute(g);
    }
}
```

Bei der Rückgängig-Aktion musst du dann den letzten Eintrag der Liste entfernen und das Panel neuzeichnen.

Ich hoffe, das war einigermaßen verständlich.

Ciao
DosCoder


----------



## Norbertus (6. Oktober 2009)

Großes Großes Danke an alle die mir hier helfen

Auch der Tipp war super! ich habe es ein bischen anders gemacht, finde es so einfach - Für die, die sowas interessiert:

Vector Klasse mit eigener Klasse verwenden, in der X-Y-Farbe stehen, diese Klasse mit den Befehlen füllen und bei der Funktion BufferedImage über SetRGB löschen und danach die Vector-Klasse durchgehen ( Minus gelöschten Bereich der History, weil Schritt zurück ).

So, nun habe ich ein allerletztes Problem , denn mein Applet an sich ist fertig 

Nur speichert er nun das Bild nicht, ich bekomme hier ein Securty Error im Firefox z.B.:

Fehler: uncaught exception: Error calling method on NPObject! [plugin exception: java.security.AccessControlException: access denied (java.io.FilePermission test.png delete)].

Dabei wollte ich das BufferedImage einfach nur in den selben Ordner des Applets über ImageIO.write schreiben? 

Wenn das Bild im selben ordner liegt muss ich doch nicht das Applet signieren? Oder doch? Wie speichert Ihr Bilder auf dem Server?!

Danke nochmals!


----------



## d4rkY89 (14. Oktober 2009)

So wie ich die Fehlermeldung interpretiere hat ein Applet nicht die Rechte Dateien vom PC zu löschen. Dann könnte ja jeder einfach mal von Browser aus einem alle möglichen Daten löschen.

-> plugin exception: java.*security.AccessControlException*: access denied (java.io.FilePermission test.png *delete*)

Offensichtlich löscht ImageIO vorhandene Dateien und legt sie dann zum Schreiben neu an.

Allerdings kenn ich mich mit den "Rechten" eines Applets nicht wirklich aus. Wäre für mich jedenfalls eine logische Erklärung.

Gruß d4rkY


----------

