如何从 JFileChooser 中放置图像?

Posted

技术标签:

【中文标题】如何从 JFileChooser 中放置图像?【英文标题】:How to put an image from a JFileChooser? 【发布时间】:2017-10-07 07:16:02 【问题描述】:

我在使用 Graphics 将图像放入 jPanel 时遇到问题。我有下一个代码:

    JFileChooser navegador = new JFileChooser();
    if (navegador.showOpenDialog(null) == 0) 
        try 
            BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
            lienzo.paintComponents(imagenAbrir.getGraphics());
         catch (IOException e) 
            JOptionPane.showMessageDialog(this, "Ocurriò un error al guardar la imàgen");
        
    

代码是按钮的一部分,用户可以从任何路径中选择图像,但它不会在面板中显示任何内容。可能是什么问题?

【问题讨论】:

添加一些更相关的代码,因为没有人知道lienzo是什么! lienzo 是西班牙文中的画布,我猜……而 OP 指的是 JPanel 对象…… 对不起,lienzo 是 JPanel 是的,它只是 JPanel 对象的名称 永远不要自己打电话给paintComponent,这不是你的责任。查看Painting in AWT and Swing 和Performing Custom Painting 了解有关绘画工作原理以及您应该如何使用它的更多详细信息,然后查看How to use lables 以获得显示图像的简单解决方案 【参考方案1】:

我认为您必须使用 BufferedImage 对象而不是 Graphics 对象来更改方法

@Override
            public void actionPerformed(ActionEvent e) 
                JFileChooser navegador = new JFileChooser();
                if (navegador.showOpenDialog(null) == 0) 
                    try 
                        BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
                        //drawPan.paintComponents(imagenAbrir.getGraphics());
                        drawPan.drawImage(imagenAbrir);
                     catch (IOException ie) 
                        JOptionPane.showMessageDialog(null, "Ocurriò un error al guardar la imàgen");
                    
                
            

然后,如果您想绘制图像,请自行创建自定义的 JPanel 类。 每次在代码中调用 repaint 方法时,都会自动调用 JComponent 的 paintCompoent 方法。

final class ImagePane extends JPanel 

            private static final long serialVersionUID = 1L;
            private BufferedImage myImage;

            public ImagePane(final BufferedImage myImage) 
                this.myImage = myImage;
            

            @Override
            public Dimension getPreferredSize() 
                return new Dimension(240, 220);
            

            public void drawImage(BufferedImage img)
            
                this.myImage = img;
                repaint();
            

            @Override
            protected void paintComponent(Graphics g) 
                super.paintComponent(g);
                if (myImage != null) 
                    Graphics2D g2d = (Graphics2D) g.create();
                    int x = (getWidth() - myImage.getWidth()) / 2;
                    int y = (getHeight() - myImage.getHeight()) / 2;
                    g2d.drawImage(myImage, x, y, this);
                    g2d.dispose();
                
            

        

这里是完整的源代码。

public class JFileChooserTest 

    static Runnable doRun = new Runnable()
    
        final class ChooseAction implements ActionListener
        
            final ImagePane drawPan;

            ChooseAction(final ImagePane drawPan)
            
                this.drawPan = drawPan;
            


            @Override
            public void actionPerformed(ActionEvent e) 
                JFileChooser navegador = new JFileChooser();
                if (navegador.showOpenDialog(null) == 0) 
                    try 
                        BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
                        //drawPan.paintComponents(imagenAbrir.getGraphics());
                        drawPan.drawImage(imagenAbrir);
                     catch (IOException ie) 
                        JOptionPane.showMessageDialog(null, "Ocurriò un error al guardar la imàgen");
                    
                
            

        

        final class ImagePane extends JPanel 

            private static final long serialVersionUID = 1L;
            private BufferedImage myImage;

            public ImagePane(final BufferedImage myImage) 
                this.myImage = myImage;
            

            @Override
            public Dimension getPreferredSize() 
                return new Dimension(240, 220);
            

            public void drawImage(BufferedImage img)
            
                this.myImage = img;
                repaint();
            

            @Override
            protected void paintComponent(Graphics g) 
                super.paintComponent(g);
                if (myImage != null) 
                    Graphics2D g2d = (Graphics2D) g.create();
                    int x = (getWidth() - myImage.getWidth()) / 2;
                    int y = (getHeight() - myImage.getHeight()) / 2;
                    g2d.drawImage(myImage, x, y, this);
                    g2d.dispose();
                
            

        

        @Override
        public void run() 
            final JFrame frame = new JFrame();
            //frame.setSize(new Dimension(300,400));

            JPanel lienzo = new JPanel();
            lienzo.setLayout(new BorderLayout());

            ImagePane drawPan = new ImagePane(null);
            JButton drawMe = new JButton("draw me");
            lienzo.add(drawMe, BorderLayout.NORTH);
            lienzo.add(drawPan, BorderLayout.CENTER);

            frame.add(lienzo);

            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);

            drawMe.addActionListener(new ChooseAction(drawPan));
        

    ;

    public static void main(String[] args)
    

        SwingUtilities.invokeLater(doRun);

    

希望对你有所帮助。

【讨论】:

不使用drawImage()还有其他方法吗?我希望它像 Paint 那样工作,我的意思是,打开文件,而不是绘制图像,因为我还有其他按钮可以做类似的事情,它只是添加不同的图像,我不知道你是否明白。 我认为打开图像文件或从某些资源中绘制图像没有什么区别。你可以在这里查看我的答案***.com/questions/37712371/… ...“浏览器”按钮从 jfilechooser 类中读取图像文件并显示出来。【参考方案2】:

代码是按钮的一部分,用户可以从任何路径中选择图像,但它不会在面板中显示任何内容。可能是什么问题?

基本上,这不是自定义绘画在 Swing 中的工作方式。千万不要自己打电话给paintComponentpaintComponents,这不是你的责任。

您要做的是通过其Graphics 上下文将图像绘制到组件

查看Painting in AWT and Swing 和Performing Custom Painting,了解有关绘画如何工作以及您应该如何使用它的更多详细信息

那就看看How to use lables 一个简单的图片显示解决方案

您也可以查看How to set a background picture in JPanel。它演示了使用 JLabel 和自定义组件来显示图像

【讨论】:

我很想知道为什么这会被否决,在使用 Swing 以及它的绘画过程如何工作时,OP 显然缺乏理解,最好的解决方案是教程 也许它被否决了,因为有些人更喜欢简单的方法(准备使用/复制和粘贴代码)而不是学习如何去做(阅读教程)[:-| .无论如何,我要 +1 @CarlosHeuberger 禁止我们教人们如何钓鱼并自力更生;)【参考方案3】:

那么,您想在显示一些基本图像的面板上添加图像吗? 如果是这样,有一些技巧可以做到这一点。 我在网上准备了两张图片(恐怕这些是授权图片)

那么,现在我在你的班级上放了三个按钮

JButton drawMe = new JButton("draw me");
JButton pickMe = new JButton("pick me");
JButton clearMe = new JButton("clear me");

我决定让 DrawAction 类重用三个动作命令,即绘制、拾取和清除。

drawMe.addActionListener(drawAct);
drawMe.setActionCommand("draw");
pickMe.addActionListener(drawAct);
pickMe.setActionCommand("pick");
clearMe.addActionListener(drawAct);
clearMe.setActionCommand("clear");

我们将再次看到 ImagePane 类。如果要在图像上添加图像,则应该有一个从 JComponent 继承的 paintcomponent 方法,无论您想使用什么组件。

'draw me'按钮是在清空bufferedimage类的数组列表中的图像列表中的所有图像后设置基础图像。

public void drawImage(BufferedImage img)

    if (imageList.size() > 0) imageList.clear();
    imageList.add(img);
    repaint();

“pick me”按钮是将图像添加到图像列表的方法。

public void addImage(BufferedImage imagenAbrir) 
    imageList.add(imagenAbrir);
    repaint();

最后一个是清除按钮,刷新和清除图像列表中的所有图像缓冲区。

public void clearImage() 
     imageList.clear();
     isClear = true;
     repaint();

这是我在面板上清除图像的技巧,它是通过使用某些特定颜色(灰色)重新绘制画布(此时为 jPanel)来完成的。 主要方法paintComponent如下..

@Override
protected void paintComponent(Graphics g) 
    super.paintComponent(g);

    if(isClear)
    
        Graphics2D g2d = (Graphics2D) g.create();
        Rectangle2D rectangle = new Rectangle2D.Double(0,0,getWidth(),getHeight());
        g2d.setPaint(Color.GRAY);
        g2d.fill(rectangle);
        g2d.dispose();

        isClear = false;
        return;
    


    if (imageList.size() > 0) 
        BufferedImage img = null;
        for(int i = 0; i < imageList.size(); i++)
        
            img = imageList.get(i);
            Graphics2D g2d = (Graphics2D) g.create();
            int x = (getWidth() - img.getWidth()) / 2;
            int y = (getHeight() - img.getHeight()) / 2;
            g2d.drawImage(img, x, y, this);
            g2d.dispose();
        
    

最后,您阅读了下面的代码如何处理动作命令以及 java 的组件,

@Override
public void actionPerformed(ActionEvent e) 

    if(e.getActionCommand().equals("draw"))
    
        JFileChooser navegador = new JFileChooser();
        if (navegador.showOpenDialog(null) == 0) 
            try 
                BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
                //drawPan.paintComponents(imagenAbrir.getGraphics());
                drawPan.drawImage(imagenAbrir);
             catch (IOException ie) 
                JOptionPane.showMessageDialog(null, "Ocurrio un error al guardar la imagen");
            
        
    
    else if(e.getActionCommand().equals("pick"))
    
        JFileChooser navegador = new JFileChooser();
        if (navegador.showOpenDialog(null) == 0) 
            try 
                BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
                //drawPan.paintComponents(imagenAbrir.getGraphics());
                drawPan.addImage(imagenAbrir);
             catch (IOException ie) 
                JOptionPane.showMessageDialog(null, "Ocurrio un error al guardar la imagen");
            
        
    
    else if(e.getActionCommand().equals("clear"))
    
        drawPan.clearImage();
    

正如您所看到的代码,每次单击“pick me”或“draw me”按钮时都需要选择一个文件。

完整的源代码

package com.tobee.ui.test;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class JFileChooserTest 

    static Runnable doRun = new Runnable()
    
        final class DrawAction implements ActionListener
        
            final ImagePane drawPan;

            DrawAction(final ImagePane drawPan)
            
                this.drawPan = drawPan;
            


            @Override
            public void actionPerformed(ActionEvent e) 

                System.out.println(e.getActionCommand());

                if(e.getActionCommand().equals("draw"))
                
                    JFileChooser navegador = new JFileChooser();
                    if (navegador.showOpenDialog(null) == 0) 
                        try 
                            BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
                            //drawPan.paintComponents(imagenAbrir.getGraphics());
                            drawPan.drawImage(imagenAbrir);
                         catch (IOException ie) 
                            JOptionPane.showMessageDialog(null, "Ocurriò un error al guardar la imàgen");
                        
                    
                
                else if(e.getActionCommand().equals("pick"))
                
                    JFileChooser navegador = new JFileChooser();
                    if (navegador.showOpenDialog(null) == 0) 
                        try 
                            BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
                            //drawPan.paintComponents(imagenAbrir.getGraphics());
                            drawPan.addImage(imagenAbrir);
                         catch (IOException ie) 
                            JOptionPane.showMessageDialog(null, "Ocurriò un error al guardar la imàgen");
                        
                    
                
                else if(e.getActionCommand().equals("clear"))
                
                    drawPan.clearImage();
                
            

        

        final class ImagePane extends JPanel 

            private static final long serialVersionUID = 1L;
            private boolean isClear;

            private List<BufferedImage> imageList;

            public ImagePane()
            
                imageList = new ArrayList<BufferedImage>();
                isClear = false;
            

            public void clearImage() 
                imageList.clear();
                isClear = true;
                repaint();
            

            public void addImage(BufferedImage imagenAbrir) 
                imageList.add(imagenAbrir);
                repaint();
            

            @Override
            public Dimension getPreferredSize() 
                return new Dimension(240, 220);
            

            public void drawImage(BufferedImage img)
            
                if (imageList.size() > 0) imageList.clear();
                imageList.add(img);
                repaint();
            

            @Override
            protected void paintComponent(Graphics g) 
                super.paintComponent(g);

                if(isClear)
                
                    Graphics2D g2d = (Graphics2D) g.create();
                    Rectangle2D rectangle = new Rectangle2D.Double(0,0,getWidth(),getHeight());
                    g2d.setPaint(Color.GRAY);
                    g2d.fill(rectangle);
                    g2d.dispose();

                    isClear = false;
                    return;
                


                if (imageList.size() > 0) 
                    BufferedImage img = null;
                    for(int i = 0; i < imageList.size(); i++)
                    
                        img = imageList.get(i);
                        Graphics2D g2d = (Graphics2D) g.create();
                        int x = (getWidth() - img.getWidth()) / 2;
                        int y = (getHeight() - img.getHeight()) / 2;
                        g2d.drawImage(img, x, y, this);
                        g2d.dispose();
                    
                
            

        

        @Override
        public void run() 
            final JFrame frame = new JFrame();

            JPanel lienzo = new JPanel();
            lienzo.setLayout(new BorderLayout());


            JPanel optionPan = new JPanel();
            ImagePane drawPan = new ImagePane();
            JButton drawMe = new JButton("draw me");
            JButton pickMe = new JButton("pick me");
            JButton clearMe = new JButton("clear me");

            DrawAction drawAct = new DrawAction(drawPan);

            optionPan.add(drawMe);
            optionPan.add(pickMe);
            optionPan.add(clearMe);

            lienzo.add(optionPan, BorderLayout.NORTH);
            lienzo.add(drawPan, BorderLayout.CENTER);

            frame.add(lienzo);

            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);

            drawMe.addActionListener(drawAct);
            drawMe.setActionCommand("draw");
            pickMe.addActionListener(drawAct);
            pickMe.setActionCommand("pick");
            clearMe.addActionListener(drawAct);
            clearMe.setActionCommand("clear");
        

    ;

    public static void main(String[] args)
    

        SwingUtilities.invokeLater(doRun);

    

【讨论】:

以上是关于如何从 JFileChooser 中放置图像?的主要内容,如果未能解决你的问题,请参考以下文章

如何在包含系统图像的背景按钮中放置渐变?

JFileChooser 过滤器

如何在两个等高的列中放置 3 个图像?

如何在 Angular Material 的对话框中放置图像?

Tailwind:如何在导航栏父 div 中放置图像

如何在 Bootstrap 3 div 中放置图像?