# paintComponent /paint/ update/ offscreenImage / Graphics2D /



## podi (2. Feb 2006)

Tag Freunde,
wer Lust bzw kurz Zeit  hat und mir gern helfen möchte, der möge mal bitte den folgenden revolutionären Code ausführen und mir bei folgenden Fragen helfen:


1) wie ändere ich den Hintergrund des off Images ? (alle Versuche haben nix gebracht, auch unter der Verwendung eines BufferedImage und (Graphics2D.setBackground)


2) wenn ich in der Methode mouseDragged paint/paintComponent bzw update aufrufe funktioniert das Zeichenprogramm so wie es sein sollte. Wenn ich dagegen repaint() aufrufe, kommt es zu Aussetzern beim Zeichnen.


Kann mir da jemand den Zusammenhang bzw die Ursache erklären???
ganz schön verwirrend das alles...


danke




```
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 * 
 * @author Synthie
 * 
 *
 */
public class Übung11_Lösung2 extends JFrame 
{
	
	private JPanel buttonPanel;

	private JButton colorChooserButton, clearButton;

	private Color newColor;	

	public Übung11_Lösung2() 
	{
		super("Scribbler");		
		buttonPanel = new JPanel();
		buttonPanel.setBackground(Color.WHITE);
		colorChooserButton = new JButton("Show Color Chooser");
		
		colorChooserButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				newColor = JColorChooser.showDialog(Übung11_Lösung2.this,
						"Choose Color", null);						
			}
		});		
		
		
		buttonPanel.add(colorChooserButton);
		
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(500,500);
		// setResizable(false);
		setLocationRelativeTo(null);

		getContentPane().add(new DrawingPanel(), BorderLayout.CENTER);
		getContentPane().add(buttonPanel, BorderLayout.SOUTH);

	}

	class DrawingPanel extends JPanel
	{	
		Image off = null;			
		int oldX, oldY,newX,newY;
		
		public DrawingPanel() 		
		{				
			
			addMouseListener(new MouseAdapter()
			{
				public void mousePressed(MouseEvent e) 
				{
					
					oldX = e.getX();
					oldY = e.getY();					
				}
			});

			addMouseMotionListener(new MouseMotionAdapter() 
			{
				public void mouseDragged(MouseEvent e)
				{					
					newX = e.getX();
					newY = e.getY();
					
					paint(getGraphics());
					
					/*funzt auch
					paintComponent(getGraphics());
					update(getGraphics());
					*/			
					
					//hmm?
					//repaint();
					oldX = newX;
					oldY = newY;
							
				}				
			});					
			
		}
	
	     public void paintComponent ( Graphics gfx ) 
	     {	    	
	    	 if (off == null) 
	         {	            
	            off = createImage(getWidth(),getHeight());	            
	         }	        
	    	 
	    	 Graphics g = off.getGraphics();
	    	 //off.setzeHintergrundfarbe(ich will weiß!!!)
	    	 g.setColor(newColor);
	    	 g.drawLine(oldX,oldY,newX,newY);	    	 
	    	 
	         gfx.drawImage(off,0,0,this);	         
	     }	     
	   
	}// class DrawingPanel

		


	public static void main(String[] args)
	{
		new Übung11_Lösung2().setVisible(true);
	}

}
```


----------



## Beni (2. Feb 2006)

1) Ein Bild ist eine Gitter von Pixeln. "Vordergrund" und "Hintergrund" haben in diesem Zusammenhang keine Bedeutung, sowas gibt es nicht bei einem Bild.
Du könntest es mal mit ein bisschen Transparenz versuchen, ein BufferedImage mit ARGB-Model sollte sowas können. Dann musst du den Hintergrund zuerst zeichnen, und dann das Bild darüber legen.

2) repaint wäre schon das Richtige. Machst du sonst noch irgendwelche zeitintensiven Berechnungen?


----------



## podi (2. Feb 2006)

Nee das Programm macht nix weiter 


es geht nur darum, dass eben nicth mehr richtig gezeichnet wird wenn ich an der stelle repaint() benutze. Man probiere es doch einfach mal aus.
paintComponent() zB liefert ein richtiges Zeichnen, so wie es sein soll.
repaint() dagegen zeichnet keine flüssigen linien sondern einfach nur punkte :-/


----------



## Beni (3. Feb 2006)

Synthesist hat gesagt.:
			
		

> Man probiere es doch einfach mal aus.


Wo du recht hast, hast du recht.

Hier mit repaint:

```
public class Übung11_Lösung2 extends JFrame
{
   
   private JPanel buttonPanel;

   private JButton colorChooserButton, clearButton;

   private Color newColor;   

   public Übung11_Lösung2()
   {
      super("Scribbler");      
      buttonPanel = new JPanel();
      buttonPanel.setBackground(Color.WHITE);
      colorChooserButton = new JButton("Show Color Chooser");
      
      colorChooserButton.addActionListener(new ActionListener()
      {
         public void actionPerformed(ActionEvent e)
         {
            newColor = JColorChooser.showDialog(Übung11_Lösung2.this,
                  "Choose Color", null);                  
         }
      });      
      
      
      buttonPanel.add(colorChooserButton);
      
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setSize(500,500);
      // setResizable(false);
      setLocationRelativeTo(null);

      getContentPane().add(new DrawingPanel(), BorderLayout.CENTER);
      getContentPane().add(buttonPanel, BorderLayout.SOUTH);

   }

   class DrawingPanel extends JPanel
   {   
      Image off = null;         
      int oldX, oldY,newX,newY;
      
      public DrawingPanel()       
      {            
         
         addMouseListener(new MouseAdapter()
         {
            public void mousePressed(MouseEvent e)
            {
               
               oldX = e.getX();
               oldY = e.getY();               
            }
         });

         addMouseMotionListener(new MouseMotionAdapter()
         {
            public void mouseDragged(MouseEvent e)
            {               
               newX = e.getX();
               newY = e.getY();
               
               //paint(getGraphics());
               
               /*funzt auch
               paintComponent(getGraphics());
               update(getGraphics());
               */         
           
               if (off == null)
               {              
                  off = createImage(getWidth(),getHeight());              
               }          
             
               Graphics g = off.getGraphics();
               g.setColor(newColor);
               g.drawLine(oldX,oldY,newX,newY);          
             
               //hmm?
               repaint();
               oldX = newX;
               oldY = newY;
                     
            }            
         });               
         
      }
   
        public void paintComponent ( Graphics gfx )
        {          
             gfx.drawImage(off,0,0,this);            
        }        
      
   }// class DrawingPanel

      


   public static void main(String[] args)
   {
      new Übung11_Lösung2().setVisible(true);
   }

}
```
repaint arbeitet verzögert (das sparrt einiges an Ressourcen), aber damit wird auch dein Befehl was auf das Bild zu malen verzögert. Aber du kannst auch direkt auf das Bild malen, und es "ab und zu" mal anzeigen lassen.


----------



## podi (3. Feb 2006)

Ok so klappts.

Danke auch für die Antwort zu der Frage mit dem "Hintergrund". Geht nun auch.
Ich habe ein BufferedImage genommen


```
off = new BufferedImage(getWidth(),getHeight(),BufferedImage.TRANSLUCENT);
```


..die Hintergrundfarbe des Panels normal im Konstruktuor wie gewünscht gesetzt und das BufferImage drübergelegt.

C'est ca.


----------

