# Problem mit JPanel bzw p a i n t



## sweikelt (29. Mai 2008)

hi,

ich möchte im rahmen eines programmierbeleges ein malprogramm erstellen, mit dem man mit der maus malen kann( im prinzip ein ms-paint klon)
mein problem besteht darin, dass meine linien, die ich mit der maus ziehe, verschwinden, sobald ich die maus wieder drücke....in einem anderen programm habe ich diesen code schon relativ erfolgreich verwendet, aber bei diesem hier kann ich den fehler absolut nicht finden.
es wäre super, wenn mir jemand einen tipp geben könnte, denn ich verzweifle echt langsamt.
hier mal der code:

1. Klasse... Zeichenpanel


```
import javax.swing.*;

import java.awt.*;

public class Malflaeche extends JPanel
{

	private static final long serialVersionUID = -2169353357630986770L;

	private Point aktuellerPunkt;
	
	private Point vorigerPunkt;
	
	public Malflaeche()
	{
		
		super();
		setSize(600,500);
		setBackground(Color.WHITE);
		setVisible(true);
		
		Steuerung s = new Steuerung(this);
		addMouseListener(s);
		addMouseMotionListener(s);
	
	}
	
	public void setAktuellerPunkt(Point p)
    {
        aktuellerPunkt = p;
    }

    public void neuerAktuellerPunkt(Point p)
    {
        /*vorigerPunkt = aktuellerPunkt;
        aktuellerPunkt = p;*/
    	vorigerPunkt = p;
    }
    
    public void update(Graphics g)
    {
    	paint(g);
    }

    
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        
        Graphics2D g2 = (Graphics2D) g;
        
    	       
    			g2.setColor(Color.RED);
    			g2.drawLine(10, 10, 100, 50 );
    			g2.drawRect(20, 40, 20, 20);
    			g2.drawOval(30, 30, 20, 20);
    			
    			if (aktuellerPunkt != null)
    			{
    			g.setColor(Color.BLACK);
    			g.drawLine(aktuellerPunkt.x,aktuellerPunkt.y,vorigerPunkt.x,vorigerPunkt.y);
    			
    			}
    		    System.out.println("Paint component");
    		    
    			
    }
    
    
}
```

hier das JFrame


```
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;


import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;


public class Fenster extends JFrame implements ActionListener 
{
	

	/**
	 * 
	 */
	private static final long serialVersionUID = 7715627779008693636L;
	

	private Malflaeche panel;
	
	private JMenuBar mbar;
	
	private JMenu mbild;
	
	private JMenuItem mneu;
	
	private JMenuItem msave;
	
	private JMenuItem mload;
	
	private JMenuItem mend;
	
	private JMenu mstyle;
	
	private JRadioButtonMenuItem mpencil;
	
	private JRadioButtonMenuItem mrect;
	
	private JRadioButtonMenuItem mcircle;
	
	private ButtonGroup mbgstyle;
	
	private JMenu mcolor;
	
	private JRadioButtonMenuItem mrot;
	   
	private JRadioButtonMenuItem mgruen;
	   
	private JRadioButtonMenuItem mblau;
	   
	private JRadioButtonMenuItem mcyan;
	   
	private JRadioButtonMenuItem mmagenta;
	   
	private JRadioButtonMenuItem mgelb;
	   
	private JRadioButtonMenuItem mschwarz;
	
	private ButtonGroup mbgcolor;

	private JMenu hcolor;
	
	private JRadioButtonMenuItem hrot;
	   
	private JRadioButtonMenuItem hgruen;
	   
	private JRadioButtonMenuItem hblau;
	   
	private JRadioButtonMenuItem hcyan;
	   
	private JRadioButtonMenuItem hmagenta;
	   
	private JRadioButtonMenuItem hgelb;
	   
	private JRadioButtonMenuItem hschwarz;
	
	private ButtonGroup mbghcolor;

	
	public Fenster()
	{
		super("Malen");
		Dimension screen = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); 
        this.setSize(screen);  this.setVisible(true);
		this.setSize(600,300);
		this.setVisible(true);
        
        mbar = new JMenuBar();
        
        mbild = new JMenu("Bild");     
        mneu = new JMenuItem("Neu");
        msave = new JMenuItem("Speichern");
        mload = new JMenuItem("Laden");
        mend = new JMenuItem("Beenden");
        
        mbar.add(mbild);
        mbild.add(mneu);
        mbild.add(msave);
        mbild.add(mload);
        mbild.add(mend);
        
        mstyle = new JMenu("Zeichenart");
        mpencil = new JRadioButtonMenuItem("Stift");
        mrect = new JRadioButtonMenuItem("Rechteck");
        mcircle = new JRadioButtonMenuItem("Kreis");
        mbgstyle = new ButtonGroup(); //nur eine Auswahl möglich
        
        mbar.add(mstyle);
        mstyle.add(mpencil);
        mstyle.add(mrect);
        mstyle.add(mcircle);
        mbgstyle.add(mpencil);
        mbgstyle.add(mrect);
        mbgstyle.add(mcircle);
        
        mcolor= new JMenu("Zeichenfarbe");
        mrot = new JRadioButtonMenuItem ("Rot");
        mgruen = new JRadioButtonMenuItem ("Grün");
        mblau = new JRadioButtonMenuItem ("Blau");
        mcyan = new JRadioButtonMenuItem ("Cyan");  
        mmagenta = new JRadioButtonMenuItem ("Magenta");
        mgelb = new JRadioButtonMenuItem ("Gelb");
        mschwarz = new JRadioButtonMenuItem ("Schwarz");
        mbgcolor = new ButtonGroup();  //nur eine Auswahl möglich
        mbar.add(mcolor);
        mcolor.add(mrot);
        mcolor.add(mgruen);
        mcolor.add(mblau);
        mcolor.add(mcyan);
        mcolor.add(mmagenta);
        mcolor.add(mgelb);
        mcolor.add(mschwarz);
        mbgcolor.add(mrot);
        mbgcolor.add(mgruen);
        mbgcolor.add(mblau);
        mbgcolor.add(mcyan);
        mbgcolor.add(mmagenta);
        mbgcolor.add(mgelb);
        mbgcolor.add(mschwarz);
        
        mrot.setBackground(Color.RED);
        mgruen.setBackground(Color.GREEN);
        mblau.setBackground(Color.BLUE);
        mcyan.setBackground(Color.CYAN);
        mmagenta.setBackground(Color.MAGENTA);
        mgelb.setBackground(Color.YELLOW);
        mschwarz.setBackground(Color.BLACK);
        mblau.setForeground(Color.WHITE);	//zur besseren Betrachtung die Textfarbe auf weiß
        mschwarz.setForeground(Color.WHITE);//zur besseren Betrachtung die Textfarbe auf weiß
        
        hcolor= new JMenu("Hintergrundfarbe");
        hrot = new JRadioButtonMenuItem ("1");
        hgruen = new JRadioButtonMenuItem ("2");
        hblau = new JRadioButtonMenuItem ("3");
        hcyan = new JRadioButtonMenuItem ("4");  
        hmagenta = new JRadioButtonMenuItem ("5");
        hgelb = new JRadioButtonMenuItem ("6");
        hschwarz = new JRadioButtonMenuItem ("7");
        mbghcolor = new ButtonGroup();	//nur eine Auswahl möglich
        mbar.add(hcolor);
        hcolor.add(hrot);
        hcolor.add(hgruen);
        hcolor.add(hblau);
        hcolor.add(hcyan);
        hcolor.add(hmagenta);
        hcolor.add(hgelb);
        hcolor.add(hschwarz);
        mbghcolor.add(hrot);
        mbghcolor.add(hgruen);
        mbghcolor.add(hblau);
        mbghcolor.add(hcyan);
        mbghcolor.add(hmagenta);
        mbghcolor.add(hgelb);
        mbghcolor.add(hschwarz);
        
        hrot.setBackground(Color.RED);
        hgruen.setBackground(Color.GREEN);
        hblau.setBackground(Color.BLUE);
        hcyan.setBackground(Color.CYAN);
        hmagenta.setBackground(Color.MAGENTA);
        hgelb.setBackground(Color.YELLOW);
        hschwarz.setBackground(Color.BLACK);

        this.setJMenuBar(mbar);
        
    	mneu.addActionListener(this);
        msave.addActionListener (this);
        mload.addActionListener (this);
        mend.addActionListener (this);
        mpencil.addActionListener (this);
        mrect.addActionListener (this);
        mcircle.addActionListener (this);
        mrot.addActionListener (this);
        mgruen.addActionListener (this);
        mblau.addActionListener (this);
        mcyan.addActionListener (this);
        mmagenta.addActionListener (this);
        mgelb.addActionListener (this);
        mschwarz.addActionListener (this);
        hrot.addActionListener (this);
        hgruen.addActionListener (this);
        hblau.addActionListener (this);
        hcyan.addActionListener (this);
        hmagenta.addActionListener (this);
        hgelb.addActionListener (this);
        hschwarz.addActionListener (this);
        
        
	 
	}
	public void showWindow()
	{
		panel = new Malflaeche();
        getContentPane().add(BorderLayout.CENTER,panel);
		setVisible(true);
		System.out.println("Panel erstellt");
		
	}

	
	

	
	public void actionPerformed (ActionEvent e) {
        String aktion = e.getActionCommand();
        if (aktion.equals ("Neu"))
        {    	
        	
        	
        	
        }
        
        if (aktion.equals ("Beenden")) {
           this.dispose();
           System.out.println("Anwendung geschlossen");
        }
        if (aktion.equals ("Rot")) {
        	
        	
           
        }
        if (aktion.equals ("Grün")) {
        	
           
           
        }
        if (aktion.equals ("Blau")) {
        	
           
        }
        if (aktion.equals ("Cyan")) {
        	
           
        }
        if (aktion.equals ("Magenta")) {
        	
           
        }
        if (aktion.equals ("Gelb")) {
        	
           
        }
        if (aktion.equals ("Schwarz")) {
        	
           
        }
        if (aktion.equals ("1")) {
        	
        	panel.setBackground(Color.RED);
        	System.out.println("Farbe gewählt");
            
        }
        if (aktion.equals ("2")) {
        	
        	panel.setBackground(Color.GREEN);
        	System.out.println("Farbe gewählt");
            
        }
        if (aktion.equals ("3")) {
        	
        	panel.setBackground(Color.BLUE);
        	System.out.println("Farbe gewählt");
        	
        }
        if (aktion.equals ("4")) {
        	
        	panel.setBackground(Color.CYAN);
        	System.out.println("Farbe gewählt");
            
        }
        if (aktion.equals ("5")) {
        	
        	panel.setBackground(Color.MAGENTA);
        	System.out.println("Farbe gewählt");
            
        }
        if (aktion.equals ("6")) {
        	
        	panel.setBackground(Color.YELLOW);
        	System.out.println("Farbe gewählt");
            
        }
        if (aktion.equals ("7")) {
        	
        	panel.setBackground(Color.BLACK);
        	System.out.println("Farbe gewählt");
            
        }
        panel.repaint();

        
	}

	
	public static void main(String[] args) 
	{
		Fenster f = new Fenster();
        JFrame.setDefaultLookAndFeelDecorated(false);	//bei Windows wird die Taskleiste nicht verdeckt
        f.setExtendedState(JFrame.MAXIMIZED_BOTH);
        f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        f.showWindow();
        //Malflaeche mf = new Malflaeche();
        //mf.setVisible(true);
        
        

        
        

        

	}

}
```

und die steuerungsklasse


```
import java.awt.*;
import java.awt.event.*;


class Steuerung implements MouseListener, MouseMotionListener
{
	boolean capture = false;
    /**
     *  die zu steuernde MausMalen-Anwendung
     */
	Malflaeche anwendung;

    /**
     *  der Konstruktor erhält die zu steuernde MausMalen-Anwendung
     *
     * @param  anw  die zu steuernde MausMalen-Anwendung
     */
    public Steuerung(Malflaeche anw)
    {
        anwendung = anw;
    }

    /**
     *  die mousePressed()-Methode wird beim Drücken der Maus-Taste aufgerufen
     *  sie ermittelt den Punkt, wo dies eintrat,
     *  und gibt ihn an die Anwendung weiter
     *
     * @param  e  das Maus-Ereignis
     */
    public void mousePressed(MouseEvent e)
    {
        Point p = e.getPoint();
        anwendung.setAktuellerPunkt(p);
    }

    /**
     *  die mouseReleased()-Methode wird beim Loslassen der Maus-Taste aufgerufen

     *  dies löst hier keine Reaktion aus
     *
     * @param  e  das Maus-Ereignis
     */
    public void mouseReleased(MouseEvent e)
    { 
    	//capture = false;
    }

    /**
     *  die mouseClicked()-Methode wird nach dem Drücken und Wiederloslassen
     *  der Maus-Taste aufgerufen

     *  dies löst hier keine Reaktion aus
     *
     * @param  e  das Maus-Ereignis
     */
    public void mouseClicked(MouseEvent e)
    { 
    	/*Point p = e.getPoint();
        anwendung.neuerAktuellerPunkt(p);
        anwendung.repaint();*/
    	
    }

    /**
     *  die mouseEntered()-Methode wird beim Eintritt der Maus-Taste ins Fenster aufgerufen

     *  dies löst hier keine Reaktion aus
     *
     * @param  e  das Maus-Ereignis
     */
    public void mouseEntered(MouseEvent e)
    { }

    /**
     *  die mouseExited()-Methode wird beim Austritt der Maus-Taste aus dem Fenster aufgerufen

     *  dies löst hier keine Reaktion aus
     *
     * @param  e  das Maus-Ereignis
     */
    public void mouseExited(MouseEvent e)
    { }

    /**
     *  die mouseMoved()-Methode wird beim Bewegen der Maus ohne gedrückte Taste aufgerufen

     *  dies löst hier keine Reaktion aus
     *
     * @param  e  das Maus-Ereignis
     */
    public void mouseMoved(MouseEvent e)
    { 
    	/*if (!capture) return;
    	Point p = e.getPoint();
        anwendung.neuerAktuellerPunkt(p);
        anwendung.repaint();*/
    }

    /**
     *  die mouseDragged()-Methode wird beim Bewegen der Maus mit gedrückter Taste aufgerufen

     *  sie ermittelt den Punkt, wo dies eintrat,

     *  teilt der Anwendung das Eintreffen eines neuen aktuellen Punktes mit

     *  und fordert die Neudarstellung des Malfensters an
     *
     * @param  e  das Maus-Ereignis
     */
    public void mouseDragged(MouseEvent e)
    {
    	//if (!capture) return;
        Point p = e.getPoint();
        anwendung.neuerAktuellerPunkt(p);
        anwendung.repaint();
        System.out.println("Maus gezogen");
        
    }
    
    
    
}
```


----------



## SlaterB (29. Mai 2008)

vor jedem paint wird der Bildschirm gelöscht,
wenn du nur die letzte Linie zeichnest, ist auch nicht mehr zu sehen,

2 Möglichkeiten:
a) alle Linien/ sonstigen Informationen in irgendeiner Form sammeln und ablegen 
und in jedem paint() das Bild von Anfang an komplett neumalen

b) nicht auf den flüchtigen Bildschirm malen sondern z.B. auf ein Image,
dieses speichern und auf den Bildschirm immer nur das Image painten


----------



## sweikelt (29. Mai 2008)

danke für deine schnelle antwort, aber ich hätte vielleicht dazu schreiben sollen, dass ich ein änfanger bin u noch nicht so viel ahnung davon hab

also wie mal ich denn auf ein Image und speichere dieses?
ist das nicht etwas rechenintensiv?


----------



## SlaterB (29. Mai 2008)

tja, für einen Anfänger ist das alles ja auch eigentlich nix,
versuche es aus der Literatur zu erlernen:
http://www.tutego.com/java/articles/Doppelpufferung-Java-Double-Buffering.html

http://www.google.de/search?hl=de&q=java+double+buffering&meta=

---------

rechnenintensiv ist es nicht, nein,
falls du b) meinst, zu welchem ich auch die Links gepostet habe,

a) ist bei vielen Linien durchaus etwas aufwendig,
Informationen in Listen zu speichern sollte dagegen weniger das Problem sein,
aber das erkläre ich auch nicht im Detail,
einfach die Punkte als Objekte in eine Liste, dann könntest du sie wieder auslesen und von Punkt zu Punkt eine Linie malen,

b) ist aber eh besser


----------



## sweikelt (29. Mai 2008)

^^

ok ich hätte eh eher zu b) geneigt.

also zusammenfassend kann man sagen, dass ich ein image erstellen muss, auf welches dann die punkte/linien gezeichnet werden sollen und bei jeder aktualisierung die alten und die neuen punkte gezeichnet werden müssen
oO, na da hab ich ja was vor


----------



## SlaterB (29. Mai 2008)

auf das Image müssen bei jeder Aktualisierung nur die neuen Punkte gezeichnet werden,
deshalb verwendet man ja gerade das Image, damit es die alten Zeichnungen speichert

das Image wird nur einmal am Anfang erstellt,
aber nicht im Konstruktor, erst beim ersten paint()-Aufruf, siehe Link


----------



## sweikelt (29. Mai 2008)

ich hab schon mal mit ner doppelbufferung rumprobiert, nur leider war das ergebnis das, dass wenn ich auf nen button hintergrundfarbe ännder(zb. rot) geklickt hab, dann musste ich nocheinmal klicken(egal wohin), damit die hintergrundfarbe angenommen wird und das zweite problem war, dass die hintergrundfarbe alles vorher gemalte einfach überschrieben hat


----------

