Image laden

  • Themenstarter Themenstarter Guest
  • Beginndatum Beginndatum
Status
Nicht offen für weitere Antworten.
G

Guest

Gast
Hallo, ich habe gestern erstmals versucht eine Netzwerkapplikation zu erstellen und da kamen gleich einige Fragen auf. Zu allererst einmal der Code:

Code:
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.event.*;

public class NetTest extends JFrame implements ActionListener{
	int frameWidth, frameHeight;
	URL url;
	URLConnection urlConnect;
	Toolkit kit;
	
	Image img;
	JLabel urlLabel;
	JTextField urlText;
	ImagePanel imagePanel;
	JButton okButton;
	
	public NetTest(String title, int frameWidth, int frameHeight){
		super(title);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.frameWidth = frameWidth;
		this.frameHeight = frameHeight;
		Container cp = this.getContentPane();
		cp.setLayout(new GridBagLayout());
		cp.setPreferredSize(new Dimension(frameWidth, frameHeight));
		kit = Toolkit.getDefaultToolkit();
		this.setLocation(kit.getScreenSize().width/2-frameWidth/2,
			kit.getScreenSize().height/2-frameHeight/2);
		GridBagConstraints con = new GridBagConstraints();
		urlLabel = new JLabel("URL:");
		urlText = new JTextField(9);
		imagePanel = new ImagePanel(img);
		imagePanel.setBorder(BorderFactory.createCompoundBorder(
			BorderFactory.createLineBorder(Color.black),
				BorderFactory.createEmptyBorder(2,2,2,2)));
		okButton = new JButton("OK");
		okButton.addActionListener(this);
		
		con.gridx = 0; con.gridy = 0;
		con.gridwidth = 1; con.gridheight = 1;
		con.weightx = 1; con.weighty = 1;
		con.fill = GridBagConstraints.BOTH;
		con.anchor = GridBagConstraints.CENTER;
		con.insets = new Insets(1,1,1,1);
		con.ipadx = 0; con.ipady = 0;
		cp.add(urlLabel, con);
		
		con.gridx = 1; con.gridy = 0;
		con.gridwidth = 3; con.gridheight = 1;
		con.weightx = 1; con.weighty = 1;
		con.fill = GridBagConstraints.BOTH;
		con.anchor = GridBagConstraints.CENTER;
		con.insets = new Insets(1,1,1,1);
		con.ipadx = 0; con.ipady = 0;
		cp.add(urlText, con);
		
		con.gridx = 4; con.gridy = 0;
		con.gridwidth = 1; con.gridheight = 1;
		con.weightx = 1; con.weighty = 1;
		con.fill = GridBagConstraints.BOTH;
		con.anchor = GridBagConstraints.CENTER;
		con.insets = new Insets(1,1,1,1);
		con.ipadx = 0; con.ipady = 0;
		cp.add(okButton, con);
		
		con.gridx = 0; con.gridy = 1;
		con.gridwidth = 5; con.gridheight = 1;
		con.weightx = 1; con.weighty = 100;
		con.fill = GridBagConstraints.BOTH;
		con.anchor = GridBagConstraints.CENTER;
		con.insets = new Insets(1,1,1,1);
		con.ipadx = 0; con.ipady = 0;
		cp.add(imagePanel, con);
		
		pack();
		setVisible(true);
	}
	
	public void actionPerformed(ActionEvent evt){
		String cmd = evt.getActionCommand();
		if(cmd.equals("OK")){
			try{
				url = new URL(urlText.getText());
				Object obj = url.getContent();
				if(obj instanceof ImageProducer){
					img = kit.createImage((ImageProducer)obj);
					imagePanel.repaint();
				}
			}
			catch(MalformedURLException exc){
				System.err.println(exc);
			}
			catch(IOException exc){
				System.err.println(exc);
			}
		}
	}
	
	public static void main(String[] args){
		NetTest net = new NetTest("Pic Loader", 200, 300);
	}
}


Code:
import java.awt.*;
import javax.swing.*;

public class ImagePanel extends JPanel{
	Image img;		
	
	public ImagePanel(Image img){
		super();
		this.img = img;
	}
	
	public void paintComponent(Graphics g){
		super.paintComponent(g);
		g.drawImage(img, 0, 0, this);
	}
}

Nun habe ich folgende Frage: Wieso wird das geladene Bild nicht im Panel gezeichnet bzw. was mache ich falsch? Desweiteren ist mir bis heute irgendwie nie richtig klar geworden, was es nun für einen Unterschied macht ob ich bei einem JPanel die paintComponents oder paintComponent Methode überschreibe (habe vorher awt grafikoberflächen erstellt). Warum sollte man oder warum sollte man nicht die eine oder andere Methode überschreiben und wo liegen die Unterschiede? JPanel erbt ja beide und müsste deshalb mit beiden Methode neu zeichnen können.

Vielen Dank 🙂
 
Also ich würde dir raten anstatt deines ImagePanels eine andere Componente zu Verwenden.

ImageIcon
und
JLabel zum Beispiel....

Mit ImageIcon kannst du schön und sauber Bilder laden.
Und sie dann mit JLabel an die gewünschte stelle setzen.


Zum Beispiel:
Code:
ImageIcon imageIcon = new ImageIcon("mein/Pfad_zum_Bild/bild.jpg");
JLabel label = new JLabel(imageIcon);
 
sockeqwe hat gesagt.:
Also ich würde dir raten anstatt deines ImagePanels eine andere Componente zu Verwenden.

ImageIcon
und
JLabel zum Beispiel....

Mit ImageIcon kannst du schön und sauber Bilder laden.
Und sie dann mit JLabel an die gewünschte stelle setzen.


Zum Beispiel:
Code:
ImageIcon imageIcon = new ImageIcon("mein/Pfad_zum_Bild/bild.jpg");
JLabel label = new JLabel(imageIcon);

Hallo und danke für deine Antwort.

Meine Fragen hast du jedoch nicht beantwortet ... und warum sollte ich ein ImageIcon nehmen bzw. was verstehst du unter "sauber [...] laden".

Gruß
 
Also ich würde Bilder über ImageIO laden - ist zeitgemäßer. Wenn du unbedingt übers Toolkit laden möchtest, dann musst du einen MediaTracker verwenden, der wartet, bis das Bild fertig geladen ist.
 
Hobbit_Im_Blutrausch hat gesagt.:
Also ich würde Bilder über ImageIO laden - ist zeitgemäßer. Wenn du unbedingt übers Toolkit laden möchtest, dann musst du einen MediaTracker verwenden, der wartet, bis das Bild fertig geladen ist.

Mh, danke für den Tipp. Trotzdem hat das alles nichts mit meinen oben erwähnten fragen zu tun 🙁
 
doch. Meine Antwort beantwortet höchstwahrscheinlich (hab mir deinen Quellcode nicht näher angesehen) deine Frage, warum das Bild nicht angezeigt wird.

Überschrieben werden sollte paintComponent (ohne s).
 
Hobbit_Im_Blutrausch hat gesagt.:
doch. Meine Antwort beantwortet höchstwahrscheinlich (hab mir deinen Quellcode nicht näher angesehen) deine Frage, warum das Bild nicht angezeigt wird.

Überschrieben werden sollte paintComponent (ohne s).

Tut mir leid, es funktioniert immer noch nicht. Meine Frage war aber warum paintComponent und nicht paintComponents? JPanel erbt doch beide Methoden.
 
Dann zeig noch mal Code.

paintComponent ist die Swing-Methode, die von JComponent kommt. paintComponents ist die AWT-Methode, die von einem Container kommt. Was ist jetzt logischer? Auf eine Komponente zu zeichnen, oder auf einen Container? 😉
 
Hobbit_Im_Blutrausch hat gesagt.:
Dann zeig noch mal Code.

paintComponent ist die Swing-Methode, die von JComponent kommt. paintComponents ist die AWT-Methode, die von einem Container kommt. Was ist jetzt logischer? Auf eine Komponente zu zeichnen, oder auf einen Container? 😉

Danke, ist ja eigentlich logisch ... Hier nochmal der Code: (Das ImagePanel ist gleich geblieben)

Code:
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.event.*;

public class NetTest extends JFrame implements ActionListener{
	int frameWidth, frameHeight;
	URL url;
	URLConnection urlConnect;
	Toolkit kit;
	
	Image img;
	JLabel urlLabel;
	JTextField urlText;
	ImagePanel imagePanel;
	JButton okButton;
	
	public NetTest(String title, int frameWidth, int frameHeight){
		super(title);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.frameWidth = frameWidth;
		this.frameHeight = frameHeight;
		Container cp = this.getContentPane();
		cp.setLayout(new GridBagLayout());
		cp.setPreferredSize(new Dimension(frameWidth, frameHeight));
		kit = Toolkit.getDefaultToolkit();
		this.setLocation(kit.getScreenSize().width/2-frameWidth/2,
			kit.getScreenSize().height/2-frameHeight/2);
		GridBagConstraints con = new GridBagConstraints();
		urlLabel = new JLabel("URL:");
		urlText = new JTextField(9);
		imagePanel = new ImagePanel(img);
		imagePanel.setBorder(BorderFactory.createCompoundBorder(
			BorderFactory.createLineBorder(Color.black),
				BorderFactory.createEmptyBorder(2,2,2,2)));
		okButton = new JButton("OK");
		okButton.addActionListener(this);
		
		con.gridx = 0; con.gridy = 0;
		con.gridwidth = 1; con.gridheight = 1;
		con.weightx = 1; con.weighty = 1;
		con.fill = GridBagConstraints.BOTH;
		con.anchor = GridBagConstraints.CENTER;
		con.insets = new Insets(1,1,1,1);
		con.ipadx = 0; con.ipady = 0;
		cp.add(urlLabel, con);
		
		con.gridx = 1; con.gridy = 0;
		con.gridwidth = 3; con.gridheight = 1;
		con.weightx = 1; con.weighty = 1;
		con.fill = GridBagConstraints.BOTH;
		con.anchor = GridBagConstraints.CENTER;
		con.insets = new Insets(1,1,1,1);
		con.ipadx = 0; con.ipady = 0;
		cp.add(urlText, con);
		
		con.gridx = 4; con.gridy = 0;
		con.gridwidth = 1; con.gridheight = 1;
		con.weightx = 1; con.weighty = 1;
		con.fill = GridBagConstraints.BOTH;
		con.anchor = GridBagConstraints.CENTER;
		con.insets = new Insets(1,1,1,1);
		con.ipadx = 0; con.ipady = 0;
		cp.add(okButton, con);
		
		con.gridx = 0; con.gridy = 1;
		con.gridwidth = 5; con.gridheight = 1;
		con.weightx = 1; con.weighty = 100;
		con.fill = GridBagConstraints.BOTH;
		con.anchor = GridBagConstraints.CENTER;
		con.insets = new Insets(1,1,1,1);
		con.ipadx = 0; con.ipady = 0;
		cp.add(imagePanel, con);
		
		pack();
		setVisible(true);
	}
	
	public void actionPerformed(ActionEvent evt){
		String cmd = evt.getActionCommand();
		if(cmd.equals("OK")){
			try{
				url = new URL(urlText.getText());
				Object obj = url.getContent();
				if(obj instanceof ImageProducer){
					img = getToolkit().createImage((ImageProducer)obj);
					MediaTracker track = new MediaTracker(imagePanel);
					track.addImage(img, 0);
					try{
						track.waitForAll();
					}
					catch(InterruptedException exc){
						System.out.println("Loading finished");
					}
					imagePanel.repaint();
				}
			}
			catch(MalformedURLException exc){
				System.err.println(exc);
			}
			catch(IOException exc){
				System.err.println(exc);
			}
		}
	}
	
	public static void main(String[] args){
		NetTest net = new NetTest("Pic Loader", 200, 300);
	}
}
 
@ Hobbit: Dass das bild nicht lädt liegt doch aber nicht am fehlenden MeidaTracker. Bei mir lädt der Code auch nicht.
 
Also zu den vorhergehenden Posts: Es ist tatsächlich das Beste, das Bild in der paintComponent zu zeichnen und kein ImageIcon zu nehmen. Sun empfiehlt das sogar explizit, um Bilder skaliert anzuzeigen (http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html). Ich würde allerdings kein JPanel nehmen, wenn Du nicht unbedingt dessen Funktionalität benötigst. Ein JComponent tut es dann eigentlich auch. Warum Dein Code nicht funktioniert weiß ich nicht. Der folgende funktioniert auf alle Fälle:


Code:
public class ImageComponent extends JComponent {
	private static final long serialVersionUID = -2077784274430624977L;
	private Image image = null;

	public ImageComponent(Image image) {
		this.image = image;
	}

	public ImageComponent() {

	}

	public void setImage(Image image) {
		this.image = image;
		repaint();
	}

	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2 = (Graphics2D) g;
		g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
				RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		g2.setRenderingHint(RenderingHints.KEY_RENDERING,
				RenderingHints.VALUE_RENDER_QUALITY);
		if (image != null)
			g2.drawImage(image, 0, 0, getWidth(), getHeight(), null);
		
		g2.dispose();
	}

}

Ciao,
Wolfgang
 
vielen Dank Wolfgang.

Den Fehler findet aber trotzdem niemand oer? 🙁
 
Doch.
Du willst das Bild zur Laufzeit anzeigen. Also musst du entweder das Panel zur Laufzeit mit dem Bild in den JFrame setzten, oder so, wie ich es hier mal gemacht habe, das Bild zur Laufzeit ins Panel setzen.
Ein repaint() auf dem Panel (Zeile 90 in deiner NetTest.java) hilft gar nichts, wenn du das Bild nicht auch vorher dem Panel übergibst.

Code:
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.imageio.ImageIO;

public class NetTest extends JFrame implements ActionListener{
   private JLabel urlLabel;
   private JTextField urlText;
   private ImagePanel imagePanel;
   private JButton okButton;

   public NetTest(String title){
      super(title);
      setDefaultCloseOperation(EXIT_ON_CLOSE);
      setLayout(new GridBagLayout());
      setSize(600, 500);
      setLocationRelativeTo(null);
      
      urlLabel = new JLabel("URL:");
      urlText = new JTextField();
      
      imagePanel = new ImagePanel();
      imagePanel.setBorder(BorderFactory.createLineBorder(Color.black));
            
      okButton = new JButton("OK");
      okButton.addActionListener(this);

      GridBagConstraints con = new GridBagConstraints();
      con.insets = new Insets(0,2,0,0);
      add(urlLabel, con);

      con.gridx = 1;
      con.weightx = 1.0;
      con.insets = new Insets(0,2,0,2);
      con.fill = GridBagConstraints.HORIZONTAL;
      add(urlText, con);

      con.gridx = 2;
      con.weightx = 0.0;
      con.insets = new Insets(1,0,1,1);
      con.fill = GridBagConstraints.NONE;
      add(okButton, con);

      con.gridx = 0; con.gridy = 1;
      con.gridwidth = 3;
      con.weighty = 1.0;
      con.fill = GridBagConstraints.BOTH;
      add(imagePanel, con);

      setVisible(true);
   }

   public void actionPerformed(ActionEvent evt){
      if(evt.getActionCommand().equals("OK")){
         if(!urlText.getText().equals("")) {
            try {
               imagePanel.setImage(ImageIO.read(new URL(urlText.getText())));
            }
            catch(MalformedURLException exc){
               JOptionPane.showMessageDialog(
                  this,
                  "Der angegebene URL ist fehlerhaft und kann nicht verarbeitet werden!",
                  "MalformedURLException",
                  JOptionPane.ERROR_MESSAGE);
               exc.printStackTrace();
            }
            catch(IOException exc){
               JOptionPane.showMessageDialog(
                  this,
                  "Fehler beim Lesen der Bildquelle!",
                  "IOException",
                  JOptionPane.ERROR_MESSAGE);
               exc.printStackTrace();
            }
            catch(NullPointerException exc){
               JOptionPane.showMessageDialog(
                  this,
                  "Der angegebene URL zeigt auf eine Resource, die nicht verarbeitet werden!",
                  "NullPointerException",
                  JOptionPane.ERROR_MESSAGE);
               exc.printStackTrace();
            }
         }

      }
   }

   public static void main(String[] args){
      NetTest net = new NetTest("Pic Loader");
   }
}

Code:
import java.awt.*;
import javax.swing.*;

public class ImagePanel extends JPanel{
   private Image img;

   public ImagePanel() {
      super(null);
   }

   public ImagePanel(Image img){
      this();
      setImage(img);
   }
   
   public void setImage(Image img) {
      this.img = img;
      repaint();
   }

   public void paintComponent(Graphics g){
      super.paintComponent(g);
      if(img != null) {
         g.drawImage(img, 0, 0, this);
      }
   }
}
 
Vielen Dank 🙂 Könntest du mir das mit dem "zur Laufzeit" etwas genauer erklären?

gruß
 
Das Hinzufügen von Elementen zu einer GUI funktioniert zur Laufzeit etwas anders, weil die GUI bereits sichtbar ist und alle Komponenten angepasst und ausgerichtet sind. Wenn du zur Laufzeit GUI-Komponenten hinzufügst, muss die Oberfläche und deren Platzverhältnisse neu berechnet und ausgegeben werden.
Mit "zur Laufzeit" ist gemeint, dass das Programm bereits angezeigt wird und vom Benutzer bedient werden kann.
 
Ok, vielen Dank!

Ich hätte noch eine letzte Frage: Was muss ich machen damit, falls das Bild zu groß für den Frame ist, die JScrollPane angezeigt wird. Bzw. wie füge ich dem Frame selber eine JScrollPane hinzu?
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben