# ImageIcon Größe ändern



## Felix (9. Sep 2006)

Hallo,

ich will ein 1,3Megapixel-Bild auf einen JButton abbilden. Aber natürlich ist das der Button so viel zu groß. Jetzt suche ich eine Möglichkeit einen ImageIcon in der Größe zu verändern, damit der Button in mein Layout passt. Kennt ihr eine Möglichkeit wie ich das machen kann?

gruß
Felix


----------



## kaie (10. Sep 2006)

Hier ein schneller Lösungsversuch (ungetestet!):

```
public static ImageIcon erzeugeIcon( File bilddatei, int groesse )
{
    try
    {
         Image i = ImageIO.read(bilddatei);
         int b = i.getWidth(null);
         int h = i.getHeight(null);
         int f = Math.max(b/groesse,h/groesse);
         BufferedImage erg = new BufferedImage( groesse, groesse, BufferedImage.TYPE_INT_RGB );
         erg.getGraphics().drawImage( i, groesse-b/f/2,groesse-h/f/2,b/f,h/f,null );
         return new ImageIcon(erg);
    } catch( Exception e )
    {
        return null;
    }
}
```

Aufruf erfolgt mit:

```
JButton b = new JButton( erzeugeIcon( new File("c:\\test.jpg",50) );
```

Es wird allerdings immer ein quadratisches Bild zurückgegeben. Wenn Du das nicht willst, ändere folgende Zeilen:

```
BufferedImage erg = new BufferedImage( b/f, h/f, BufferedImage.TYPE_INT_RGB );
          erg.getGraphics().drawImage( i,0,0,b/f,h/f,null );
```


----------



## Felix (10. Sep 2006)

Danke, der Code funktioniert insoweit, dass die Bilder verkleinert dargestellt werden. Aber leider ist nurnoch ein ganz kleiner Ausschnitt vom bild zu sehen... Am linken und oberen Rand sind nämlich ziemlich dicke schwarze Balken und dann erst kommt das Bild, das zwar in der richtigen Größe zu sein scheint, aber wegen den Balken nicht mehr ganz zu sehen ist. Hast du eine Idee woran das liegen könnte?

gruß
Felix


----------



## kaie (10. Sep 2006)

Klar weiss ich, woran es liegen kann: ICH KANN NICHT RECHNEN!  :? 

In der drawImage-Methode fehlt hinter groesse jeweils ein /2
Und wenn Du die schwarzen Balken weghaben möchtest, ändere TYPE_INT_RGB in TYPE_INT_ARGB

Dann sollte es funktionieren. Sorry für den ungetesteten Code!


----------



## Felix (10. Sep 2006)

Danke, jetzt funktioniert es so wie ich will. Der Code wie ich ihn benutze:


```
public static ImageIcon erzeugeIcon( File bilddatei, int groesse )
    {
        try{
             Image i = ImageIO.read(bilddatei);
             int b = i.getWidth(null);
             int h = i.getHeight(null);
             int f = Math.max(b/groesse,h/groesse);
             BufferedImage erg = new BufferedImage( groesse, groesse, BufferedImage.TYPE_INT_ARGB );
             erg.getGraphics().drawImage( i, groesse-b/f,groesse-h/f,b/f,h/f,null );
             return new ImageIcon(erg);
        } catch( Exception e )
        {
            return null;
        }
    }
```

die Bilder werden auch nicht verzogen, nur das Imageicon ist halt quadratisch, aber das kann ich ja noch ändern.

gruß
Felix


----------



## Guest (10. Sep 2006)

Dadurch, dass Du das /2 beim Zeichnen weggelassen hast, wird das Bild nicht mehr zentriert, sondern immer rechts unten im Quadrat angeordnet. Wenn das Deinen Wünschen entspricht, freut es mich, Dir geholfen zu haben!


----------



## Felix (10. Sep 2006)

das problem war ja, das der linke obere rand zentriert angezeigt wurde, was dazu führte, dass man nicht das ganze bild sehen konnte.

du warst mir eine sehrgroße hilfe, da ich zum ersten mal bilder in der größe verändere...

________________________
EDIT:

aber irgendwie bekomm ich das nicht hin, dass die Bilder mittig angeordnet werden...


----------



## Felix (10. Sep 2006)

Kannst du mir bitte noch erklären, was genau in dieser Zeile passiert, bwz. wie er funktioniert?


```
int f = Math.max(b/groesse,h/groesse);
```


----------



## Tobias (10. Sep 2006)

Der Ausdruck gibt b / groesse zurück, wenn b / groesse > h / groesse, ansonsten h / groesse.

mpG
Tobias


----------



## André Uhres (10. Sep 2006)

```
Icon icon = new ImageIcon( new ImageIcon( getClass().getResource("image00001x.jpg") )
                .getImage().getScaledInstance(80, -1, Image.SCALE_SMOOTH) );
```


----------



## Felix (11. Sep 2006)

@Tobis: danke, jetzt versteh ich die Zeile auch...

@ Andrè: entschuldige, leider kann ich mit deinem Code grad so nicht  wirklich viel anfangen, ich hab ihn in eine eigene Methode kopiert und die Pfadangabe durch einen bei mir gültigen Pfad ersetzt, aber es kam immer eine runtimeexception... ich wäre dir dankbar, wenn du mir den Code näher erläutern könntest...


----------



## thE_29 (11. Sep 2006)

Es geht auch mit Pfad laden


```
Icon icon = new ImageIcon( new ImageIcon("C:\\pfad\\zum\\bild\\bild.jpg" )
                .getImage().getScaledInstance(80, -1, Image.SCALE_SMOOTH) );
```


----------



## Tobias (11. Sep 2006)

> EDIT:
> 
> aber irgendwie bekomm ich das nicht hin, dass die Bilder mittig angeordnet werden...





> Klar weiss ich, woran es liegen kann: ICH KANN NICHT RECHNEN! icon_confused.gif
> 
> In der drawImage-Methode fehlt hinter groesse jeweils ein /2





> Dadurch, dass Du das /2 beim Zeichnen weggelassen hast, wird das Bild nicht mehr zentriert, sondern immer rechts unten im Quadrat angeordnet.



also:


```
public static ImageIcon erzeugeIcon( File bilddatei, int groesse )
{
    try
    {
         Image i = ImageIO.read(bilddatei);
         int b = i.getWidth(null);
         int h = i.getHeight(null);
         int f = Math.max(b/groesse,h/groesse);
         BufferedImage erg = new BufferedImage( groesse, groesse, BufferedImage.TYPE_INT_RGB );
         erg.getGraphics().drawImage( i, (groesse/2) - (b/f/2), (groesse/2) - (h/f/2), b/f, h/f, null );
         return new ImageIcon(erg);
    } catch( Exception e )
    {
        return null;
    }
}
```

mpG
Tobias


----------



## Felix (11. Sep 2006)

danke, mit thE 29's verschlag klappt es hervorragend, den von tobias hab ich grad erst gesehen, aber auch schonmal danke...

ansich ist mein grundporblem jetzt gelöst. 2 fragen hätte ich allerdings noch:

- wie kann ich einen JButton gerade so groß wie das bild machen?
und
- wie kann ich ein bild auf ein JPanel zeichnen, weil mit JPanel.add(ImageIcon) geht es nicht...?

gruß
felix


----------



## thE_29 (11. Sep 2006)

Beim JPanel nimmst du ein JLabel und legst das drauf!

du sagst beim Button

this.setPreferredSize(new Dimension(bild_weite,bild_höhe));

dann sollte der Button nur so groß sein!


----------



## Felix (11. Sep 2006)

das mit dem button klappt super, aber ich krieg den ImageIcon nicht auf das JLabel weil er immer schreibt dass es den Konstruktor

new JLabel(ImageIcon)

nicht gibt.


----------



## André Uhres (11. Sep 2006)

JLabel hat den Konstruktor "public JLabel(Icon image)"
ImageIcon impementiert Icon, also ist der Konstruktor genau passend:

```
ImageIcon img = new ImageIcon("...");//Oder: Icon img = new ImageIcon("");
        JLabel label = new JLabel(img);
```


----------



## Felix (11. Sep 2006)

ok, ich habs jetzt so hinbekommen, dass der code (angeblich) keine fehler mehr hat, aber das bild wird trotzdem nicht angezeigt, hier ist der Code:


```
BildPanel.removeAll();
ImageIcon i = new ImageIcon (new ImageIcon(f.getAbsoluteFile().toString()).getImage().getScaledInstance(200, -1, Image.SCALE_SMOOTH));
        
BildPanel.add(new JLabel(i));
BildPanel.repaint();
```

gruß
felix


----------



## André Uhres (11. Sep 2006)

```
if(!f.exists()){
            System.out.println("haha");
            System.exit(0);
        }
```


----------



## zubi (12. Sep 2006)

André Uhres hat gesagt.:
			
		

> ```
> if(!f.exists()){
> System.out.println("haha");
> System.exit(0);
> ...


 

Wenn das Bild gefunden wird, versuch's mal mit:

```
BildPanel.validate();
```

Wenn der Fehler beim Laden des Bildes liegt kannst du es testeshalber ins gleiche Package legen und mit

```
ImageIcon i = new ImageIcon (getClass().getResource("bildname")).getImage().getScaledInstance(200, -1, Image.SCALE_SMOOTH));
```
laden.


----------



## Felix (12. Sep 2006)

doch doch, das bild besteht schon über überprüf das ja natürlich vorher...

es wird einfach nicht angezeigt. es gibt da wohl so einen standartfehler, weil immer wenn ich was in meiner Benutzeroberfläche zur Laufzeit ändere hab ich probleme damit, nur ich komm nicht genau drauf, was es ist...

gruß
felix

__________
edit:

ich stelle gerade fest, dass wenn ich das bild auf den Label durch einen text ersetze auch nichts erscheint, wie kann ich denn herausfinden ob das label überhaupt auf das panel gelegt wird?


----------



## André Uhres (12. Sep 2006)

zubis Vorschlag: BildPanel.validate()
oder: BildPanel.revalidate()
müsste eigentlich funzen
Das BildPanel muss natürlich im JFrame liegen..


----------



## zubi (12. Sep 2006)

Poste doch mal den ganzen (relevanten) Code, sonst wird das nie was .


----------



## Felix (12. Sep 2006)

Methode init() wird von Konstruktor aufgerufen (Oberfläche mit NetBeans5 gestaltet):


```
BildPanel = new javax.swing.JPanel();
//...
 BildPanel.setLayout(BildPanelLayout);
        BildPanelLayout.setHorizontalGroup(
            BildPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 594, Short.MAX_VALUE)
        );
        BildPanelLayout.setVerticalGroup(
            BildPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 342, Short.MAX_VALUE)
        );
```

und genau da lag das problem, ich wusste nciht dass man bei NetBeans5 (ich nutze es zum ersten mal) noch ein Layout für das Panel setzten muss...

jetzt habe ich noch eine Codezeile in den Konstruktor eingefügt:


```
BildPanel.setLayout(new FlowLayout());
```

und alles klappt, bis auf, dass jetzt meine ganze Oberfläche nichtmehr gut aussieht (warum auch immer).

gruß
Felix

_____________________
Edit:

wie kann ich einem JPanel denn eine feste Breite zuweisen?


----------



## André Uhres (12. Sep 2006)

Tools | Template Manager | Java GUI Forms | JPanel Form | OPen in Editor | Design View
Im Inspector: Rechtsklick auf JPanel -> Set Layout -> FlowLayout
File | Save

Damit hast du jetzt immer JPanels mit dem Standard Layout (=FlowLayout)
Ähnlich kannst du vorgehen für JFrame und andere.


Edit: panel.setPreferredSize(..)


----------



## Felix (12. Sep 2006)

ok, da klappt jetzt alles, ich hab aber das selbe problem mit einem JPanel auf dem ich JButtons ablegen will, und da ist das Layout schon auf FlowLayout gesetzt, was gibt es denn noch für möglichkeiten?


----------



## André Uhres (13. Sep 2006)

NetBeans zeigt die gängigsten Möglichkeiten in den Properties der Komponente, wenn du das meinst..


----------



## Felix (13. Sep 2006)

ich hab folgenden code 


```
this.removeAll();
                 this.setLayout(new FlowLayout());
                 //...
                if (files != null){
            
                     for (int n = 0; n < files.length; n++){
                
                     ImageIcon ii = new ImageIcon( new ImageIcon(files[n].getAbsolutePath().toString() )
                          .getImage().getScaledInstance(-1, verticalSize, Image.SCALE_FAST) );
                
                     PictureButton newButton = new PictureButton(files[n], ii);
                     newButton.setPreferredSize(new Dimension(ii.getIconWidth(),ii.getIconHeight()));
                     newButton.addActionListener(this);
                     this.add(newButton);
                
                     }
            
                this.revalidate();
                }
```

und das erste mal (da ist das JPanel ja noch leer) führ ich nur das unter dem Command aus, und alles klappt super, aber wenn ich dann andere Bilder anzeigen lassen will, muss ich ja zuerst das JPanel leer machen, also führ cich den ganzen code aus, aber dann wird nichts mehr angezeigt...
wisst ihr warum?

gruß
felix


----------



## André Uhres (15. Sep 2006)

Dein Code funktioniert bei mir:

```
package paint;
/*
 * BildPanelDemo.java
 */
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
public class BildPanelDemo extends JFrame {
    BildPanel panel;
    public BildPanelDemo() {
        super("BildPanel Demo");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(400,300);
        setLocationRelativeTo(null);
        toolBar = new JToolBar();
        btRedisplay= new JButton();
        btRedisplay.setText("Redisplay");
        btRedisplay.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                btRedisplayActionPerformed(evt);
            }
        });
        toolBar.add(btRedisplay);
        getContentPane().add(toolBar, BorderLayout.NORTH);
        panel = new BildPanel();
        add(panel);
    }
    private void btRedisplayActionPerformed(ActionEvent evt) {
        panel.redisplayButtons();
    }
    public static void main(String args[]) {new BildPanelDemo().setVisible(true);}
    private JButton btRedisplay;
    private JToolBar toolBar;
    class BildPanel extends JPanel implements ActionListener{
        private final String PFAD1 = "c:\\img1.gif";
        private final String PFAD2 = "c:\\img2.gif";
        private File[] files = new File[]{new File(PFAD1), new File(PFAD2) };
        private int verticalSize=100;
        private boolean so;
        public BildPanel(){
            displayButtons();
        }
        private void displayButtons(){
            if (files != null){
                for (int n = 0; n < files.length; n++){
                    ImageIcon ii = new ImageIcon( new ImageIcon(files[n].getAbsolutePath().toString() )
                    .getImage().getScaledInstance(-1, verticalSize, Image.SCALE_FAST) );
                    PictureButton newButton = new PictureButton(files[n], ii);
                    newButton.setPreferredSize(new Dimension(ii.getIconWidth(),ii.getIconHeight()));
                    newButton.addActionListener(this);
                    this.add(newButton);
                }
                this.revalidate();
            }
        }
        private void redisplayButtons(){
            so = !so;
            files = new File[]{new File(so?PFAD2:PFAD1), new File(so?PFAD1:PFAD2) };
            this.removeAll();
            displayButtons();
        }
        public void actionPerformed(ActionEvent e) {
            System.out.println("ok");
        }
    }
    class PictureButton extends JButton{
        public PictureButton(File file, ImageIcon icon){
            setIcon(icon);
        }
    }
}
```


----------



## Felix (17. Sep 2006)

ok, ich hab das problem gelöst, irgend wie wird das JFrame nicht neu gezeichnet, indem ich jetzt das bild wechsel, wird es das aber und alles funktioniert so wie es soll

mfg Felix


----------

