# Panel/Icon aktualisieren



## vonDuebel (24. Mai 2011)

Hallo leuts,

Ich hab hier nen kleines Programm geschrieben. Das soll mir ein Bild anzeigen, und anschließend per Klick auf den Zoombutton das Bild zoomen. Allerdings bleibt das Bild trotz des Repaint-Befehls gleich. Wo liegt mein Fehler?

```
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;


public class BildZoomMain extends JFrame implements ActionListener{
	JPanel panel;
	JLabel label;
	JSlider slider;
	ImageIcon icon;
	BufferedImage image;
	JButton button;
	

   public BildZoomMain() throws IOException{
       super("ShowImageExample");
       panel = new JPanel();
       slider = new JSlider();
       button = new JButton("Zoom");
       panel.setLayout(new BorderLayout());
       setDefaultCloseOperation(EXIT_ON_CLOSE);
       
       File file = new File("Bilddatei");
       image = ImageIO.read(file);
       icon = new ImageIcon(image);
       label = new JLabel(icon);
       
       panel.add(label, BorderLayout.CENTER);
       panel.add(slider, BorderLayout.NORTH);
       panel.add(button, BorderLayout.SOUTH);
       add(panel);
       pack();
       setVisible(true);
       
       button.addActionListener(this);
   }
   
   public static void main(String[] args) throws IOException {
       new BildZoomMain();
   }
   
   public BufferedImage zoomIn(BufferedImage bi, int scale){
   	
   	int width = scale * bi.getWidth();
   	int height = scale * bi.getHeight();
   	
   	BufferedImage biScale = new BufferedImage(width, height, bi.getType());
   	
   	for(int i=0; i<width; i++)
   		for (int j=0; j<height; j++)
   			biScale.setRGB(i, j, bi.getRGB(i/scale, j/scale));
		return biScale;   	
   }
   
   public void actionPerformed(ActionEvent e) {
	   zoomIn(image, 5);
	   label.repaint();
   }
   
}
```


----------



## Michael... (24. Mai 2011)

Auf dem Label ist immernoch das selbe Icon. Du erzeugst zwar ein größeres Image verwendest es aber nicht.


----------



## vonDuebel (24. Mai 2011)

k, und wie sorg ich dafür dass es verwendet wird?
icon.getImage() klappt auch nicht


----------



## Michael... (24. Mai 2011)

JLabel besitzt doch eine Methode 
	
	
	
	





```
setIcon(Icon icon)
```


----------



## vonDuebel (24. Mai 2011)

also, ich hab das jetzt mal folgendermaßen implementiert:


```
public void actionPerformed(ActionEvent e) {
	   zoomIn(image, 5);
	   icon.setImage(image);
	   label.setIcon(icon);
   }
```

das Ergebnis iss allerdings das gleiche.


----------



## Michael... (24. Mai 2011)

vonDuebel hat gesagt.:


> also, ich hab das jetzt mal folgendermaßen implementiert:
> 
> 
> ```
> ...


Wenn der restliche Code gleich geblieben ist, ändert das immer noch nichts an der Tatsache, dass ein größerers Image erzeugt aber nicht verwendet wird.

In der Methode 
	
	
	
	





```
zoomIn(...)
```
 wird doch ein neues skaliertes Bild (*biScale*) erzeugt und zurückgegeben. Du verwendest aber immernoch das alte Bild in *image*.


----------



## vonDuebel (24. Mai 2011)

so, jetzt wird image mit dem returnwert von zoomIn überschrieben. Passieren tut aber trotzdem nichts.
und ja, der restliche Code ist gleich geblieben.


```
public void actionPerformed(ActionEvent e) {
	   image = zoomIn(image, 5);
	   icon.setImage(image);
	   label.setIcon(icon);
   }
```


----------



## Michael... (24. Mai 2011)

Vermutlich erkennt das JLabel bei der Vorgehensweise nicht, dass es sich um ein neues Icon handelt und aktualisiert nicht (einfach mal Fenster minimieren und wieder anzeigen lassen)

Besser ist ein neues Icon zu erzeugen.

```
label.setIcon(new ImageIcon(zoomIn(image, 5)));
```


----------



## Brainiac (25. Mai 2011)

Wurde da nicht einfach ein repaint() vergessen?


----------



## jgh (25. Mai 2011)

jo, entweder ein repaint am ende aufrufen...das funktioniert 1x einwandfrei

```
public void actionPerformed(ActionEvent e) {
		image = zoomIn(image, 5);
		icon.setImage(image);
		label.setIcon(icon);
		this.repaint();
	}
```

Das führt allerdings beim 2. Klicken des Buttons zu einer:

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space
	at java.awt.image.DataBufferInt.<init>(Unknown Source)
	at java.awt.image.Raster.createPackedRaster(Unknown Source)
	at java.awt.image.DirectColorModel.createCompatibleWritableRaster(Unknown Source)
	at java.awt.image.BufferedImage.<init>(Unknown Source)
	at sun.java2d.loops.GraphicsPrimitive.convertFrom(Unknown Source)
	at sun.java2d.loops.GraphicsPrimitive.convertFrom(Unknown Source)
	at sun.java2d.loops.MaskBlit$General.MaskBlit(Unknown Source)
	at sun.java2d.loops.Blit$GeneralMaskBlit.Blit(Unknown Source)
	at sun.java2d.loops.GraphicsPrimitive.convertFrom(Unknown Source)
	at sun.java2d.d3d.D3DGeneralBlit.Blit(Unknown Source)
	at sun.java2d.pipe.DrawImage.blitSurfaceData(Unknown Source)
	at sun.java2d.pipe.DrawImage.renderImageCopy(Unknown Source)
	at sun.java2d.pipe.DrawImage.copyImage(Unknown Source)
	at sun.java2d.pipe.DrawImage.copyImage(Unknown Source)
	at sun.java2d.pipe.ValidatePipe.copyImage(Unknown Source)
	at sun.java2d.SunGraphics2D.drawImage(Unknown Source)
	at sun.java2d.SunGraphics2D.drawImage(Unknown Source)
	at javax.swing.ImageIcon.paintIcon(Unknown Source)
	at javax.swing.plaf.basic.BasicLabelUI.paint(Unknown Source)
	at javax.swing.plaf.ComponentUI.update(Unknown Source)
	at javax.swing.JComponent.paintComponent(Unknown Source)
	at javax.swing.JComponent.paint(Unknown Source)
	at javax.swing.JComponent.paintChildren(Unknown Source)
	at javax.swing.JComponent.paint(Unknown Source)
	at javax.swing.JComponent.paintChildren(Unknown Source)
	at javax.swing.JComponent.paint(Unknown Source)
	at javax.swing.JComponent.paintChildren(Unknown Source)
	at javax.swing.JComponent.paint(Unknown Source)
	at javax.swing.JLayeredPane.paint(Unknown Source)
	at javax.swing.JComponent.paintChildren(Unknown Source)
	at javax.swing.JComponent.paintToOffscreen(Unknown Source)
	at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)



oder gleich den Vorschlag von michael13 nutzen:

```
public void actionPerformed(ActionEvent e) {
		label.setIcon(new ImageIcon(zoomIn(image, 5)));
	}
```

Allerdings kann man nur einmal zoomen. Zumindest schmeißt er bei Michael´s Lösung keine Exception!


----------



## Michael... (25. Mai 2011)

Ein repaint() hilft natürlich auch, wäre aber nicht notwendig, wenn das Label das Icon als neues/geändertes Icon erkennen würde. Man ruft ja überlicherweise nach einem setText(...) ja auch nicht explizit repaint() auf.

Die Exception kommt daher, dass bei mehrfacher Vergrößerung irgendwann der Speicher ausgeht.


----------

