# Graphics2D. repaint()



## Alex___ (18. Mrz 2008)

Hallo zusammen,

ich zeichne ein Spielfeld mit


```
BufferedImage bi = ImageIO.read(new File("feld.jpg"));
		    g2 = bi.createGraphics();
	        g2.setPaint(Color.red);
	        	        
	        label = new JLabel(new ImageIcon(bi));
```

später setze ich dort ein paar Werte:


```
g2.drawString(logik.getBox(x, y), logik.get_kastenMitteHorizontal(x), logik.get_kastenMitteVertikal(y));
```


nun habe ich aber das Problem, dass der Inhalt nicht immer sichtbar wird. Wenn nichts zu sehen ist, muss ich das Fenster erst verkleinern und wieder vergrößern - dann ist alles da.
Ein repaint() hilft komischerweise nicht.

Hat jemand eine Idee woran es liegt?

Grüße
Alex


----------



## 0x7F800000 (18. Mrz 2008)

Lädst du das bild etwa jedes mal neu, bei jedem paint-methodenaufruf? ???:L


----------



## Alex_____ (18. Mrz 2008)

Hi,

nein, der Aufruf. Hier ist die ganze Klasse:


```
public class zahlen_GUI extends JFrame implements MouseListener {

//	private Point mousePos;
	Dimension prefSize;
	private static BufferedImage image;
	static JLabel label;
	static Graphics2D g2;
	boolean klickFlag = false;
	int klick1X, klick1Y, klick2X, klick2Y;
		
		zahlen_GUI() throws IOException {
	    	BufferedImage bi = ImageIO.read(new File("feld.jpg"));
		    g2 = bi.createGraphics();
	        g2.setPaint(Color.red);
	        	        
	        label = new JLabel(new ImageIcon(bi));
	        JFrame f = new JFrame();
	        
	        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	        f.getContentPane().add(label, "West");
  
	        f.pack();
	        f.setVisible(true);
		}
		
		//Bekommt einen Wert aus der LogikMatrix und zeichnet diesen ins Feld ein
		public static void getBoxContents(Graphics2D g, int x, int y) {
			g.drawString(logik.getBox(x, y), logik.get_kastenMitteHorizontal(x), logik.get_kastenMitteVertikal(y));
		}
		
		//Löscht den grafischen Inhalt einer Box
		public void deleteBox(Graphics2D g, int x, int y) {
			g.setColor(Color.black);
			g.fillRect(x-10, y-15, 20, 17);
			repaint();
		}
	
		//Setzt einen Wert in das Spielfeld und die LogikMatrix
		public static void setBoxContents(Graphics2D g, int x, int y, String inhalt) {
			g.setColor(Color.white);			
			logik.setBox(x, y, inhalt);
			getBoxContents(g, x, y);
		}
		
		//Zeichnet das Startfeld
		public static void drawInit(Graphics2D g, int feldBreite,int startReihen){
			for(int i=0; i<=feldBreite; i++) {
				for (int i2=0; i2<= startReihen; i2++) {
					getBoxContents(g, i, i2);
				}
			}
		}

	    synchronized public void mouseClicked(MouseEvent e){
//	    	mousePos = e.getPoint();
	    	System.out.println("x: " + e.getX() );
	    	System.out.println("y: " + e.getY() );
	    	
//	    	System.out.println("Kasten hor: " + logik.get_kasten_h(e.getX()) );
//	    	System.out.println("Kasten ver: " + logik.get_kasten_v(e.getY()) ); 
//	    	System.out.println("Kasten Inahlt: " + logik.get_feld( logik.get_kasten_h(e.getX()), logik.get_kasten_v(e.getY())) ); 	
	    	
	    	//klick1X, klick1Y, klick2X, klick2Y definieren die angeklicken Kästchen
	    	if (klickFlag == false) {
	    		klickFlag = true;
	    		klick1X = logik.get_kasten_h(e.getX());
	    		klick1Y = logik.get_kasten_v(e.getY());
	    	}
	    	else
	    	{
	    		klickFlag = false;
	    		klick2X = logik.get_kasten_h(e.getX());
	    		klick2Y = logik.get_kasten_v(e.getY());
	    		System.out.println("Klick 1: " + klick1X + "," + klick1Y );
	    		System.out.println("Klick 2: " + klick2X + "," + klick2Y );
	    		
	    		if (logik.moveValid(klick1X, klick1Y, klick2X, klick2Y)) {
	    			System.out.println("Zug gültig");
	    			if (Integer.valueOf(logik.getBox(klick1X, klick1Y)) + Integer.valueOf(logik.getBox(klick2X, klick2Y)) == 10 ) {
	    				System.out.println("Summe ergibt 10!");
	    				
	    				deleteBox(g2, logik.get_kastenMitteHorizontal(klick1X), logik.get_kastenMitteVertikal(klick1Y));
	    				deleteBox(g2, logik.get_kastenMitteHorizontal(klick2X), logik.get_kastenMitteVertikal(klick2Y));
	    				setBoxContents(g2, klick1X, klick1Y, ".");
	    				setBoxContents(g2, klick2X, klick2Y, ".");
	    			}
	    		}
	    	}
	    }
	    
		/**
	    leere Implementierung (nur aus formalen Gründen vorhanden)
	    */
	    public void mouseEntered(MouseEvent e){
	    }
	    public void mouseExited(MouseEvent e){
	    }
	    public void mousePressed(MouseEvent e){
	    }
	    public void mouseReleased(MouseEvent e){
	    }
	    
	    public static void main(String[] args) throws IOException {
	    	zahlen_GUI GUI = new zahlen_GUI();
	        label.addMouseListener(GUI);
	        
	        feldoperationen.initFeld();
	        drawInit(g2, 8, 2);
	        
	        setBoxContents(g2, 5, 5, ".");
	        setBoxContents(g2, 6, 5, ".");
	        setBoxContents(g2, 4, 5, "9");
	        setBoxContents(g2, 7, 5, "1");
	        setBoxContents(g2, 8, 5, "x");
	    }
}
```


Die Methode "deleteBox" zB. zeichnet das Rechteckt nicht.  Bzw es wird erst dann sichtbar, wenn ich das Fenster verkleinere und wieder vergrößere.


----------



## 0x7F800000 (18. Mrz 2008)

ich weiss nicht was das programm tun soll, aber ich kann folgendes sagen:
1) ich habe da gar keine paint() methode entdeckt?  :bahnhof:  bin ich blind oder wie?
2) du hast ein gewaltiges problem, was die trennung von logik und grafik angeht. Methoden wie "drawInit()" haben absolut nirgendwo in keinem kontext eine existenzberechtigung, sowas ist einfach sinnlos
3) natürlich sihst du erstmal nichts wenn du eine von diesen tollen "zeichenmethoden" wie "deleteBox" aufrufst: swing ist doppeltgepuffert. Wenn du da mit dem graphics-objekt irgendetwas darauf zeichnest, zeichnest du zunächst nur im backbuffer. Erst wenn du das fenster verzerrst wird die komponente neugezeichnet, und die veränderungen kommen zum vorschein. Du müsstest zumindest mal die repaint() manuell aufrufen, damit du etwas siehst.

Aber konzentriere dich bitte vor allem auf den zweiten punkt. So ein Logik-Grafik mix ist echt einfach nur verwirrend...


----------



## Guest (18. Mrz 2008)

Hi,

in der Methode deleteBox wird repain() aufgerufen. Trotzdem passiert dort nix.
Wohin soll denn drawInit deiner Meinung nach ausgelagert werden?

Gruß
Alex


----------



## 0x7F800000 (18. Mrz 2008)

repaint() wird da aufgerufen? meinst du echt?  :wink: 

na dann schau dir doch bitte nochmal an, die repaint()-methode _welcher klasse_ da aufgerufen wird:



> zahlen_GUI() throws IOException {
> BufferedImage bi = ImageIO.read(new File("feld.jpg"));
> g2 = bi.createGraphics();
> g2.setPaint(Color.red);
> ...



dein bild auf dem du da herumpinselst ist diese BufferedImage bi
Es ist im JLabel *label*
label wiederum befindet sich in einem *JFrame f*
und das JFrame f wird völlig unabhängig von *zahlen_GUI* in dem konstruktor erstellt und dargestellt

und was tust du?

du ruftst einfach so repaint() auf. Von der zahlen_GUI klasse, die nicht einmal sichtbar ist... Was glaubst du wieviel der Label label von dieser aktion mitbekommt? richtig: gar nix...


Also: schmeiss diese ganzen bescheuerten JLabels und Panels und zusätzliche Frames einfach mal aus der kette raus, die machen einfach keinen sinn.


so sollte es aussehen (Klassennamen schreibt man übrigens GROß):

```
public class Zahlen_GUI extends JPanel implements BlahBlahListener{

    //DAS BILD IST NUR ALS HÜBSCHER HINTERGRUND, NICHT FÜR DIE LOGIK!!!
    private BufferedImage background;

    public Zahlen_GUI(){
        super();
        background=...//laden usw usw, das ist alles mehr oder weniger okay 
        
    }

    public void paint(Graphics g){
        g.drawImage(background,0,0,getWidth(),getHeight(),this);

        for(alleFelderDurchgehen){
            //LOGISCHEN zustand irgendwo sonst auslesen
            //dem zusatnd entsprechend das feld zeichnen
        }
    }
    
    public void mouseClicked(ActionEvent lalala){
        //NIX ZEICHNEN sondern nur den LOGISCHEN ZUSTAND DER FELDER ÄNDERN
        //fürs zeichnen ist schon das hier, und evtl ein paar hilfstfuktionen verantwortlich:
        repaint(); 
    }

    public static void main(String[] args){
        JFrame f=new JFrame("...");

        ...
        f.getContentPane().add(new Zahlen_GUI);
    }
}
```

auf diese art und weise strukturiert dürfte es 1) funktionieren 2) halbwegst vernünftigen code aufbau aufweisen 3)leicht in applet umzuwandeln sein

good luck have fun...


----------



## Guest (18. Mrz 2008)

Nein, so funktioniert´s leider nicht:

Exception in thread "main" java.lang.IllegalArgumentException: adding a window to a container
	at java.awt.Container.addImpl(Unknown Source)
	at java.awt.Container.add(Unknown Source)
	at zahlen_GUI.main(zahlen_GUI.java:120)


----------



## 0x7F800000 (19. Mrz 2008)

ich weiß nicht was du da angestellt hast, in meinem code war Zahlen_GUI noch ein JPanel... Keine ahnung, vielleicht hast du während des umkrempel-vorgangs vergessen "JFrame" durch "JPanel" bzw "JComponent" zu ersetzen? ich bin mir relativ sicher dass mein code funktionieren dürfte...


----------



## Guest (19. Mrz 2008)

Also ich hab´s nochmal überarbeitet. Der Fehler ist jetzt weg, allerdings wird das Hintergrund-JPG nicht angezeigt.

Hier ist der Code:


```
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;

import javax.imageio.ImageIO;
import javax.swing.*;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;


public class zahlen_GUI extends JPanel implements MouseListener {

	private static BufferedImage image;
	static Graphics2D g2;

		zahlen_GUI() throws IOException {
			super();
	    	BufferedImage bi = ImageIO.read(new File("feld.jpg"));
		    g2 = bi.createGraphics();
		}


	    synchronized public void mouseClicked(MouseEvent e){
	    	System.out.println("Mouseklick");
	    }
	    
	    public void paint(Graphics2D g) {
	    	g.drawImage(image,0,0,getWidth(),getHeight(),this);
	    }
	    
		/**
	    leere Implementierung (nur aus formalen Gründen vorhanden)
	    */
	    public void mouseEntered(MouseEvent e){
	    }
	    public void mouseExited(MouseEvent e){
	    }
	    public void mousePressed(MouseEvent e){
	    }
	    public void mouseReleased(MouseEvent e){
	    }
	    
	    public static void main(String[] args) throws IOException {
	    	JFrame f=new JFrame("...");
	    	zahlen_GUI GUI = new zahlen_GUI();
	    	f.getContentPane().add(GUI);
	    	f.pack();
	    	f.setVisible(true);
	    	
	    }
}
```


Wie würde man nun einen Mouselistener für die Klicks auf dem Hintergrund-JPG erstellen (wenn es mal angezeigt wird)?

Gruß
Alex


----------



## Guest (19. Mrz 2008)

ok, der Mouselistener funktioniert. Nur noch das Anzeigen des jpg funktioniert nicht.


----------



## 0x7F800000 (19. Mrz 2008)

von dem Thread, der die ganzen graphischen sachen zeichnet wird die methode

```
public void paint(Graphics g){
...
}
```
erwartet, mit deiner

```
public void paint(Graphics2D g){
...
}
```
kann er nichts anfangen


----------



## Guest (19. Mrz 2008)

auch dann wird kein jpg gezeichnet. probiere doch mal diesen code aus:


```
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;

import javax.imageio.ImageIO;
import javax.swing.*;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;


public class test extends JPanel implements MouseListener {

   private static BufferedImage image;
   static Graphics2D g2;

      test() throws IOException {
         super();
          BufferedImage bi = ImageIO.read(new File("feld.jpg"));
          g2 = bi.createGraphics();
      }


       synchronized public void mouseClicked(MouseEvent e){
          System.out.println("Mouseklick");
       }
      
       public void paint(Graphics g) {
          g.drawImage(image,0,0,getWidth(),getHeight(),this);
          
       }
      
      /**
       leere Implementierung (nur aus formalen Gründen vorhanden)
       */
       public void mouseEntered(MouseEvent e){
       }
       public void mouseExited(MouseEvent e){
       }
       public void mousePressed(MouseEvent e){
       }
       public void mouseReleased(MouseEvent e){
       }
      
       public static void main(String[] args) throws IOException {
          JFrame f=new JFrame("...");
          test GUI = new test();
          
          
          f.getContentPane().add(GUI);
          f.pack();
          f.setVisible(true);
          
       }
```


----------



## 0x7F800000 (19. Mrz 2008)

rofl...

du hast schon in diesem kleinen codeabschnitt das totale chaos: die Ursache dafür dass es "nicht funktioniert" ist schlicht und einfach die, dass du zwei bilder hast: *image* bleibt immer null, und das versuchst du zu zeichnen, *bi* ist eine lokale variable im konstruktor, wird geladen und weggeworfen...

so läuft es definitiv:


```
import java.awt.*; 
import java.awt.image.BufferedImage; 
import java.io.*; 

import javax.imageio.ImageIO; 
import javax.swing.*; 

import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 


public class Test extends JPanel implements MouseListener { 

   private BufferedImage image; 
   static Graphics2D g2; 

      Test(){ 
    	  super(); 
    	  try{
    		  image = ImageIO.read(new File("Sonnenuntergang.jpg"));
    		  MediaTracker tracker=new MediaTracker(this);
    		  tracker.addImage(image, 0);
    		  tracker.waitForAll();
    		  System.out.println(image);
    		  g2 = (Graphics2D)(image.getGraphics()); 
    	  }catch (Exception e){
    		  System.out.println(e);
    	  }
          addMouseListener(this);
      } 


       synchronized public void mouseClicked(MouseEvent e){ 
          System.out.println("Mouseklick"); 
          repaint();
       } 
      
       public void paint(Graphics g){ 
          g.drawImage(image,0,0,getWidth(),getHeight(),this);
       }
      
      /** 
       leere Implementierung (nur aus formalen Gründen vorhanden) 
       */ 
       public void mouseEntered(MouseEvent e){ 
       } 
       public void mouseExited(MouseEvent e){ 
       } 
       public void mousePressed(MouseEvent e){ 
       } 
       public void mouseReleased(MouseEvent e){ 
       } 
      
       public static void main(String[] args){ 
          JFrame f=new JFrame("..."); 
          f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          f.setSize(800,600);
          Test GUI = new Test(); 
          f.getContentPane().add(GUI);
          f.setVisible(true); 
          
       }
}
```
dateinamen halt beliebig ändern, habe jetzt dieses Beispielbild von Windows XP in den Projektordner gepackt...[/b]


----------

