I want to add a Image into a JPanel, the JPanel is inside JInternalFrame, and the JInternalFrame has a parent, the JDesktopPane.
I've tried with another class to add a Image from a path, and then, jPanel1 = new Imagen(<String FilePath>);
, the class will receive the path in String, in the window constructor, but it does not work. and I have tried by customizing code from the initComponents()
, the line jPanel1 = javax.swing.JPanel();
and replacing this line by jPanel1 = new Imagen();, the parameter that the constructor will receive, is the path of the image file, and this method works fine, but it only run one time (inside the initComponents() method), and I can't (or I don't known) how to replace the image from the JPanel. :(
The project starts first with a JDesptopPane, an then one JInternalFrame (1), from this internalframe, it shows other JInternalFrame(2), from this internalFrame, it shows other JInternalFrame(3), in the internalFrame 3, I want to find with a button, and JFileChooser, an image, and the path received by the filechooser, I want to set as parameter in the Imagen() class. and set the image into a JPanel that is builded into the JInternalFrame(3).
EDIT 1: Thanks for your comments. Here the code of JInternalFrame(3), the window constructor:
public AgregarContacto() {
JFileChooser jf = new JFileChooser();
jf.setDialogTitle("Elija el archivo de Imagen");
int i = jf.showOpenDialog(null);
if (i == JFileChooser.APPROVE_OPTION) {
default1 = jf.getSelectedFile().getAbsolutePath();
}
initComponents();
jPanel1= new Imagen(default1);
for (String llenarMese : p.llenarMeses()) {
Mes.addItem(llenarMese);
}
for (String llenarDia : p.llenarDias31()) {
Dia.addItem(llenarDia);
}
for (String llenarAnios : p.Anios()) {
Anio.addItem(llenarAnios);
}
}
And here the code of the class Imagen() that will receive in the Constructor a string:
public class Imagen extends JPanel {
String ruta;
private BufferedImage imag;
public Imagen(String path){
ruta = path;
try{
imag = ImageIO.read(new File("unknown.png"));
}catch(IOException ex){
JOptionPane.showMessageDialog(null, "Error " + ex.getMessage());
}
}
@Override
public void paint(Graphics g){
super.paint(g);
Image Scaledimage = imag.getScaledInstance(this.getWidth(), this.getHeight(), Image.SCALE_SMOOTH);
g.drawImage(Scaledimage, 0, 0, null);
}
}
There are a multitude of ways to do this, but, one of the more preferable, would be to provide the ImagePane
with the ability to change the image it is displaying without need to create a new instance of it.
This way, you could simply pass the ImagePane
a reference to the image you want to load and let it do it's job
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
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.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.filechooser.FileFilter;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JDesktopPane dp = new JDesktopPane() {
@Override
public Dimension getPreferredSize() {
return new Dimension(600, 600);
}
};
JInternalFrame inFrm = new JInternalFrame("Image", true, true, true, true);
inFrm.add(new ShowImagePane());
inFrm.pack();
inFrm.setVisible(true);
dp.add(inFrm);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(dp);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ShowImagePane extends JPanel {
private JFileChooser fc;
public ShowImagePane() {
setLayout(new BorderLayout());
ImagePane imagePane = new ImagePane();
add(imagePane);
JButton open = new JButton("Open...");
open.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (fc == null) {
fc = new JFileChooser();
fc.addChoosableFileFilter(new FileFilter() {
@Override
public boolean accept(File f) {
String name = f.getName().toLowerCase();
return name.endsWith(".png")
|| name.endsWith(".jpg")
|| name.endsWith(".jpeg")
|| name.endsWith(".bmp");
}
@Override
public String getDescription() {
return "Images";
}
});
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
fc.setMultiSelectionEnabled(false);
}
switch (fc.showOpenDialog(ShowImagePane.this)) {
case JFileChooser.APPROVE_OPTION:
File selected = fc.getSelectedFile();
try {
imagePane.setImageSource(selected);
} catch (IOException ex) {
ex.printStackTrace();
}
break;
}
}
});
add(open, BorderLayout.SOUTH);
}
}
public class ImagePane extends JPanel {
private BufferedImage bgImage;
private Image scaled;
public ImagePane(File source) throws IOException {
setImageSource(source);
}
public ImagePane() {
}
@Override
public void invalidate() {
super.invalidate();
resizeImage();
}
public void setImageSource(File source) throws IOException {
if (source != null) {
bgImage = ImageIO.read(source);
resizeImage();
} else {
bgImage = null;
}
}
@Override
public Dimension getPreferredSize() {
return bgImage == null ? new Dimension(200, 200) : new Dimension(bgImage.getWidth(), bgImage.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (scaled != null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - scaled.getWidth(this)) / 2;
int y = (getHeight() - scaled.getHeight(this)) / 2;
g2d.drawImage(scaled, x, y, this);
g2d.dispose();
}
}
protected void resizeImage() {
if (bgImage != null) {
if (getWidth() < getHeight()) {
scaled = bgImage.getScaledInstance(this.getWidth(), -1, Image.SCALE_SMOOTH);
} else {
scaled = bgImage.getScaledInstance(-1, getHeight(), Image.SCALE_SMOOTH);
}
repaint();
}
}
}
}
Image#getScaledInstance
is neither the fastest or, more importantly, best quality scaling algorithm. Because it can take time to re-scale an image, you should only do it when you have to.
Take a look at Java: maintaining aspect ratio of JPanel background image and Quality of Image after resize very low -- Java for more details and ideas