Добавление изображения в JPanel внутри JInternalFrame

Я хочу добавить изображение в JPanel, JPanel находится внутри JInternalFrame, а у JInternalFrame есть родитель, JDesktopPane.

Я пытался с другим классом добавить изображение из пути, а затем jPanel1 = new Imagen(<String FilePath>); класс получит путь в String в конструкторе окна, но это не работает. и я попытался настроить код из initComponents(), строку jPanel1 = javax.swing.JPanel(); и заменить эту строку на jPanel1 = new Imagen();, параметр, который получит конструктор, - это путь к файлу изображения, и этот метод работает нормально, но он запускается только один раз (внутри метода initComponents()), и я не могу (или не знаю), как заменить изображение из JPanel. :(

Проект начинается сначала с JDesptopPane, затем с одним JInternalFrame (1), из этого внутреннего фрейма он показывает другой JInternalFrame (2), из этого внутреннего фрейма он показывает другой JInternalFrame (3), во внутреннем фрейме 3, который я хочу найти с помощью кнопку и JFileChooser, изображение и путь, полученный средством выбора файлов, я хочу установить в качестве параметра в классе Imagen(). и установите изображение в JPanel, встроенное в JInternalFrame(3).

РЕДАКТИРОВАТЬ 1: Спасибо за ваши комментарии. Вот код JInternalFrame(3), конструктора окна:

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);
    }  
}

А вот код класса Imagen(), который получит в Конструктор строку:

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);
    }
}

person Allan Ramirez    schedule 19.05.2015    source источник
comment
Я хотел бы помочь, но, к сожалению, не могу загрузить проект из этого места, так как URL-адрес заблокирован в моем офисе. Не могли бы вы написать небольшую тестовую программу - SSCCE? Как вы устанавливаете изображение в панель? Используете ли вы JLabel в качестве контейнера изображений? Если да, избавьтесь от всех внутренних фреймов, создайте JFrame с JPanel с JLabel и кнопкой. Когда вы нажимаете кнопку, выберите файл и установите его на метку. Если это сработает, повторите это для своего кода с внутренними фреймами. В противном случае опубликуйте код здесь, и я могу помочь.   -  person sethu    schedule 19.05.2015
comment
Пожалуйста, не размещайте код в ссылках, а тем более в виде сжатого огромного сложного файла программы. Если вам нужна помощь здесь, вы должны сначала изолировать проблему в небольшой полностью автономной программе, которую вы можете опубликовать здесь, опять же небольшая, которую мы можем скомпилировать, запустить и которая демонстрирует вашу проблему для нас, минимальный пример программы.   -  person Hovercraft Full Of Eels    schedule 19.05.2015
comment
@sethu Отредактировано. Спасибо за ваш комментарий   -  person Allan Ramirez    schedule 19.05.2015
comment
Я хочу - Хорошо, но что не работает?   -  person MadProgrammer    schedule 19.05.2015
comment
Я не могу (или не знаю), как заменить изображение из JPanel. :( Два варианта: удалить существующую панель и создать новый экземпляр, когда вам нужно, или, что предпочтительнее, предоставить сеттер для ImagePanel, который позволяет ему изменять изображение   -  person MadProgrammer    schedule 19.05.2015
comment
Привет @MadProgrammer, когда я выбираю файл в Filechooser и устанавливаю панель = новый Imagen (путь); это не загрузило изображение в jPanel1. Помните, что это окно (JInternalFrame) находится внутри DesktopPane. Спасибо за комментарий.   -  person Allan Ramirez    schedule 19.05.2015
comment
Вам нужно снова добавить его в кадр...   -  person MadProgrammer    schedule 19.05.2015
comment
Привет @MadProgrammer, я пробовал это: try{ imag = ImageIO.read(new File("unknown.png")); ImagePane imgPane = new ImagePane(); imgPane.setImage(imag); imgPane.setRounded(true); jPanel1.add(imgPane); }catch(IOException ex){ ex.printStackTrace(); }, но это не работает;   -  person Allan Ramirez    schedule 19.05.2015
comment
Вызовите revalidate на jPanel1 ПОСЛЕ того, как вы добавили новый экземпляр ImagePane, также убедитесь, что вы сначала удалили все старые.   -  person MadProgrammer    schedule 19.05.2015


Ответы (1)


Существует множество способов сделать это, но одним из наиболее предпочтительных было бы предоставление ImagePane возможности изменять отображаемое изображение без необходимости создавать новый его экземпляр.

Таким образом, вы можете просто передать ImagePane ссылку на изображение, которое хотите загрузить, и позволить ему выполнить свою работу.

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 не является ни самым быстрым, ни, что более важно, алгоритмом масштабирования самого высокого качества. Поскольку изменение масштаба изображения может занять некоторое время, делать это следует только в случае необходимости.

Взгляните на Java: сохранение соотношения сторон фона JPanel изображение и Качество изображения после изменения размера очень low -- Java для более подробной информации и идей

person MadProgrammer    schedule 19.05.2015
comment
Спасибо, я только что использовал класс ImagePane, и я сделал: `ImagePane imgPane = new ImagePane(); try{ //imag = ImageIO.read(новый файл(неизвестный.png)); imgPane.setImageSource (новый файл (неизвестный.png)); //imgPane.setRounded(true); }catch(IOException ex){ ex.printStackTrace(); } jPanel1.add(imgPane,BorderLayout.CENTER);` - person Allan Ramirez; 19.05.2015