# gemaltes wieder löschen



## anfänger15 (22. Feb 2007)

Hallo

Bei meinem Programm soll man das was man gemalt hat auch wieder löschen können da hab ich aber nur die methode clearRect() zum löschen von Rechtecken gefunden. Gibts da auch noch andere methoden zum löschen oder wie muss man das machen?

Habe es schon Versucht z.B ein neues Rechteck in der Hintergrundfarbe zu malen um etwas anderes so zusagen zu löschen. Das geht gut nur wenn ich etwas das ich mit fill gezeichnet habe löschen will geht es nicht

Habt ihr ideeen?


----------



## nocxsville (22. Feb 2007)

Ich hab mich mit diesem Thema noch nicht wirklich beschäftigt, aber ich würde alle gemalten Objekte in einer Collection speichern. Wenn ein Objekt gelöscht werden soll dann wird es aus der Collection entfernt. Danach alle müssen Objekte neuzeichenen lassen. Geht aber bestimmt auch noch performanter.

Gruß,
nocxsville.


----------



## Marco13 (22. Feb 2007)

Naja - bei dem clearRect steht so ein Kommentar dabei
http://java.sun.com/j2se/1.5.0/docs/api/java/awt/Graphics.html#clearRect(int,%20int,%20int,%20int)
und die Aussage "das geht nicht" ist auch ein bißchen dünn. Aber eigentlich müßte es doch ein
g.setColor(Color.WHITE); // oder so
g.fillRect(x,y,w,h);
tun!?


----------



## snopy019 (22. Feb 2007)

Hi,

wir wärs, wenn du das Bild neu zeichnest (repaint()), nur das was du nimma haben willst, weg lässt?

Lg


----------



## André Uhres (23. Feb 2007)

Marco13 hat gesagt.:
			
		

> Naja - bei dem clearRect steht so ein Kommentar dabei..


Tipp: "_Graphics.clearRect_" funktioniert gut in Verbindung mit _"Graphics2D.setBackground"_


----------



## anfänger15 (23. Feb 2007)

ok danke für die hilfe


----------



## anfänger15 (23. Feb 2007)

ok hab das mal versucht ich hoffe es war so gemeint:

```
Graphics2D t = (Graphics2D) g; 
t.setBackground(Color.white);            
g.clearRect(x, y, 5, 5);
```

Damit kann man aber nur Rechtecke löschen.Linien gehen nicht ich denke das funktioniert mit clearRect nicht da man mit dem doch nur Rechtecke löschen kann, oder?


----------



## Marco13 (23. Feb 2007)

Alles was du gemalt hast, kannst du wieder löschen indem du es nochmal zeichnest - mit der Hintergrundfarbe. Aber inzwischen klingt diese Problembeschreibung (die sich iterativ (aber vermutlich nur asymptotisch) dem annähert, was du gleich im ersten Post hättest schreiben können) so, als wäre nocxsville's Vorschlag der richtige Hinweis...


----------



## anfänger15 (23. Feb 2007)

Marco13 ich hab zwar die hälfte was du mir sagen wolltest (z.B. die sich iterativ (aber vermutlich nur asymptotisch) dem annähert) nicht verstanden, aber egal.Ich wollte ja nur wissen wie man ein "Radiergummi" so wie bei paint programmiert. Falls mir da jemand helfen kann wäre ich sehr froh darüber.


----------



## anfänger15 (23. Feb 2007)

so zeichne ich in das JPanel: 
	
	
	
	





```
g.setColor(getForeground());
	for (int i=0; i < re; i++) {
	    Rectangle p = (Rectangle)rechteck.elementAt(i);
	    g.setColor((Color)Rcolor.elementAt(i));
		g.drawRect(p.x, p.y, p.width, p.height);

                }
	if (mode == RECHTECK) {
	    g.setColor(getForeground());
	    if (x2 != -1) {
                g.drawRect(x, y, w, h);
                	
                }
	    }
```

kann mir jemand helfen?
danke


----------



## Marco13 (23. Feb 2007)

Die Ausführungen mit dem "iterativ/asymptotisch" bezogen sich darauf, dass du dir vielleicht mal überlegen solltest, ob DU, wenn du die Antwort denn mal irgendwann gefunden hast, und dir die Frage, die du zuerst gestellt hast, nochmal durchliest, SELBST noch verstehen wirst, was du mit der Frage überhaupt gemeint hast, und in welchem Zusammenhang(!) du sie gestellt hast.

(Kurz: Drück dich klarer aus :wink: )

Wenn du so löschen willst, wie mit dem Radiergummi bei paint, dann solltest du das, was du malst, in ein BufferedImage malen (und in der paintComponent-Methode dann nurnoch dieses BufferedImage malen). Um in diesem BufferedImage etwas zu löschen, kannst du einfach an der Mausposition Pixel mit der gewünschten Farbe setzen (z.B. mit der Hintergrundfarbe). Wenn du nicht einzelne Pixel sondern größere Bereiche löschen willst, kannst du auch an der Mausposition in dem BufferedImage ein fillOval mit der gewünschten Farbe machen.

Pseudocode

```
BufferedImage bufferedImage = ...
Graphics imageGraphics = bufferedImage.getGraphcis();

public void paintComponent(Graphics g)
{
    super.paintComponent(g);
    g.drawImage(bufferedImage, 0, 0, this);
}

public void mouseDragged(MouseEvent e)
{
    ... // if (radier-Modus ist an)
        imageGraphics.setColor(Color.WHITE); // Hintergrundfarbe
        imageGraphics.fillOval(e.getX(), e.getY(), 2, 2); // Bereich löschen
}
```


----------



## anfänger15 (23. Feb 2007)

Danke für den Code hab heute leider keine Zeit das in mein Programm einzubauen. Werd es aber morgen versuchen


----------



## anfänger15 (24. Feb 2007)

der Code


```
public void draw(Graphics image){
 img = new BufferedImage(bildanzeige.getSize().width,bildanzeige.getSize().height, BufferedImage.TYPE_INT_RGB);

 image = img.getGraphics();
 	image.drawRect(0,0,100,100);
}
```

so zeichnet es ein Rechteck, wenn ich aber den Zeichenmous in draw festlegen will kommt es zu einem java.lang.OutOfMemory

Was mache ich falsch?


----------



## anfänger15 (24. Feb 2007)

das muss irgendwas mit dem hier zu tun haben
	
	
	
	





```
if (Label.equals("Oval")) 
  	bildanzeige.setDrawMode(CBildLeinwand.OVAL);
```
Wenn ich das weg lass und den Text des Buttons mit dem Label vergleiche und dann zeichne geht es. Dann funktioniert aber der Rectangle nicht und wenn ich was neues zeichne ist das alte wieder weg.Wenn ich es so mache kommt es zu einem java.lang.OutOfMemory fehler

Weis jemand rat?


----------



## anfänger15 (24. Feb 2007)

ok hab es gesschaft ich zeichne jetzt alles in ein Image und dann zeichne ich das image auf den JPanel allerdings hat sich beim löschen überhaubt nichts geändert.ES GEHT IMMER NOCH NICHT. Ich hab es genau so gemacht wie Marco13 es geschrieben hat aber jeden Punkt, den ich gelöscht habe wird durch die Rectangle wieder gezeichnet und ohne die Rectangle geht es nicht da dann das gemalte beim nächsten malen wieder weg ist. 

Hat jemand eine idee wie ich das machen kann?


----------



## Marco13 (25. Feb 2007)

Linke Maustaste: Malen
Rechte Maustaste: Gemaltes wieder löschen.


```
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;

class PaintPanel extends JPanel implements MouseMotionListener
{
    private BufferedImage image;
    private Graphics imageGraphics;

    public PaintPanel()
    {
        addMouseMotionListener(this);
    }

    public void paintComponent(Graphics g)
    {
        if (image == null)
        {
            image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
            imageGraphics = image.getGraphics();
        }
        g.drawImage(image, 0, 0, this);
    }

    public void mouseMoved(MouseEvent e) {}

    public void mouseDragged(MouseEvent e)
    {
        int onmask = InputEvent.BUTTON1_DOWN_MASK;
        if ((e.getModifiersEx() & onmask) == onmask)
        {
            imageGraphics.setColor(Color.RED);
        }
        else
        {
            imageGraphics.setColor(Color.BLACK);
        }
        imageGraphics.fillOval(e.getX()-6, e.getY()-6, 12,12);
        repaint();
    }
}

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

    public PaintTest()
    {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(300,300);
        PaintPanel paintPanel = new PaintPanel();

        getContentPane().setLayout(new GridLayout(1,1));
        getContentPane().add(paintPanel);
        setVisible(true);
    }
}
```

Bei dir geht das aber vermutlich nicht, weil das ja bei dir alles ganz anders ist.


----------



## anfänger15 (25. Feb 2007)

Die Idee hatte ich auch schon. Wenn man da aber dann ein einziges,nicht gefülltest Rechteck(wie in Paint) zeichnen will zeichnet es viele Rechtecke, was ja gar nicht gemacht werden soll.


----------



## Marco13 (26. Feb 2007)

Dafür würdest du dann folgendermaßen vorgehen:

In der Klasse liegt eine Variable "currentlyPaintedRectangle" (oder so). Wenn der benutzer gerade dabei ist, ein Rechteck zu malen (aber noch nicht fertig ist), dann speichert currentlyPaintedRectangle dieses Rechteck, andernfalls ist es null.

Wenn die Maus gedrückt wird (mousePressed) wird ein "currentlyPaintedRectangle" erstellt. Die Linke obere Ecke ist die Mausposition. Dieses currentlyPaintedRectangle wird erstmal NUR in der paintComponent-Methode gemalt (nachdem das bufferedImage gemalt wurde).

Wenn der Benutzer die Maus draggt, wird die rechte untere Ecke des Rechtecks verschoben, und immer repaint() aufgerufen. In der paintComponent malt er dann das bisherige Bild, und zusätzlich das Rechteck, das der Benutzer gerade erstellt.

Sobald der Benutzer die Maus losläßt (mouseReleased) wird es interessant: Dann ist das Rechteck "fertig", und kann in das Bild übertragen werden. Dann malt man EINMAL (!) das fertige(!) currentlyPaintedRectangle in das bufferedImageGraphics-Objekt. Anschließend setzt man currentlyPaintedRectangle auf null, und ruft repaint() auf. Er malt dann nurnoch das fertige Bild, das nun auch das neue Rechteck enthält.


----------



## anfänger15 (26. Feb 2007)

ah danke hilft mir bestimmt weiter kann es nur die nächste Zeit leider nicht testen, da uns unsere Lehrer gleich am ersten Tag nach den ferien 5 neue Arbeiten(KA) aufgebrummt haben.


----------



## anfänger15 (26. Feb 2007)

In welcher Klasse liegt "currentlyPaintedImage".In Graphics?
 Hab mal danach gegoogelt aber nichts gefunden!!


----------



## Marco13 (27. Feb 2007)

Es hieß nicht "currentlyPaintedImage", sondern 
"currentlyPaintedRectangle" *(oder so)*
Das sollte andeuten, dass du "irgendwo" eine solche Variable anlegen solltest. (Bei dem Code, den ich gepostet hatte, würde die in "PaintPanel" liegen). Die kann natürlich auch anders heißen. Es ging nur daraum, dass sie das Objekt speichert, das _gerade gemalt wird_, aber noch NICHT in das BufferedImage übertragen wurde.


----------



## anfänger15 (27. Feb 2007)

ok mein fehler.


----------



## HaBaLeS (27. Feb 2007)

Also wenn du wirklich den Radiergummi wollst, solltest du dir folgendes anschauen:

java.sun.com/docs/books/tutorial/2d/advanced/compositing.html

Du kannst mit Composite verschiedene Stiftypen einstellen. Einer davon ist löschen.

```
g.setComposite(AlphaComposite.Clear);
```

alles was du jetzt malst wirkt wie radieren. Falls das Bild Transparent ist wird bis zur Transparenz wegradiert. Hast du keine Transparenz, wird bis zur Hintergrundfarbe radiert. 
Nicht vergessen wieder auf den "normalen" Modus zu wechseln.


```
g.setComposite(AlphaComposite.SrcOver);
```


Diese Methode eignet sich auch sehr gut, um komplett transparente Bilder aus Java heraus zu erzeugen.

Grüße
 Falko


----------



## Marco13 (27. Feb 2007)

Das geht imho schon einen Schritt weiter: Damit könnte man erreichen, dass beim Radieren nicht vollkommen gelöscht wird, sondern dass der adiergummi "weich" ist - ich vermute, zusammen mit einem GradientPaint könnte man da schon richtig Professionell aussehende _Radierungen_ hinkriegen


----------



## anfänger15 (28. Feb 2007)

HaBaLeS danke die Idee ist gut werd ich mal ausprobieren
Danke an alle die mir geholfen haben!! :applaus:


----------

