浏览图像文件并使用 Java Swing 显示它
Posted
技术标签:
【中文标题】浏览图像文件并使用 Java Swing 显示它【英文标题】:Browse for image file and display it using Java Swing 【发布时间】:2012-11-10 20:18:49 【问题描述】:我的问题是, 单击 Browse 按钮后,它会显示目录中的所有文件以供选择, 然后选择的图像正确显示在 GUI 中。但是当我点击浏览按钮 第二次,它只显示旧图像而不显示新图像。请帮帮我。
作为参考,我上传了 UI。
package GUI;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
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.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
@SuppressWarnings("serial")
public class MainAppFrame extends JFrame
private JPanel contentPane;
File targetFile;
BufferedImage targetImg;
public JPanel panel,panel_1;
private static final int baseSize = 128;
private static final String basePath =
"C:\\Documents and Settings\\Administrator\\Desktop\\Images";
/**
* Launch the application.
*/
public static void main(String[] args)
EventQueue.invokeLater(new Runnable()
public void run()
try
MainAppFrame frame = new MainAppFrame();
frame.setVisible(true);
frame.setResizable(false);
catch (Exception e)
e.printStackTrace();
);
/**
* Create the frame.
*/
public MainAppFrame()
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 550, 400);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new BorderLayout(0, 0));
panel = new JPanel();
panel.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 1, true));
contentPane.add(panel, BorderLayout.WEST);
JButton btnBrowse = new JButton("Browse");
btnBrowse.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent e)
browseButtonActionPerformed(e);
);
JLabel lblSelectTargetPicture = new JLabel("Select target picture..");
JButton btnDetect = new JButton("Detect");
btnDetect.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent e)
);
JButton btnAddDigit = new JButton("Add Digit");
btnAddDigit.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent e)
);
JButton button = new JButton("Recognize");
button.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent e)
);
panel_1 = new JPanel();
panel_1.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 1, true));
GroupLayout gl_panel = new GroupLayout(panel);
gl_panel.setHorizontalGroup(
gl_panel.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel.createSequentialGroup()
.addGap(6)
.addGroup(gl_panel.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel.createSequentialGroup()
.addComponent(lblSelectTargetPicture)
.addGap(6)
.addComponent(btnBrowse))
.addGroup(gl_panel.createSequentialGroup()
.addGap(10)
.addComponent(btnDetect)
.addGap(18)
.addComponent(btnAddDigit))))
.addGroup(gl_panel.createSequentialGroup()
.addGap(50)
.addComponent(button))
.addGroup(gl_panel.createSequentialGroup()
.addContainerGap()
.addComponent(panel_1, GroupLayout.PREFERRED_SIZE, 182, GroupLayout.PREFERRED_SIZE))
);
gl_panel.setVerticalGroup(
gl_panel.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel.createSequentialGroup()
.addGroup(gl_panel.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel.createSequentialGroup()
.addGap(7)
.addComponent(lblSelectTargetPicture))
.addGroup(gl_panel.createSequentialGroup()
.addGap(3)
.addComponent(btnBrowse)))
.addGap(18)
.addComponent(panel_1, GroupLayout.PREFERRED_SIZE, 199, GroupLayout.PREFERRED_SIZE)
.addGap(22)
.addGroup(gl_panel.createParallelGroup(Alignment.BASELINE)
.addComponent(btnDetect)
.addComponent(btnAddDigit))
.addGap(18)
.addComponent(button)
.addContainerGap())
);
panel.setLayout(gl_panel);
public BufferedImage rescale(BufferedImage originalImage)
BufferedImage resizedImage = new BufferedImage(baseSize, baseSize, BufferedImage.TYPE_INT_RGB);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, baseSize, baseSize, null);
g.dispose();
return resizedImage;
public void setTarget(File reference)
try
targetFile = reference;
targetImg = rescale(ImageIO.read(reference));
catch (IOException ex)
Logger.getLogger(MainAppFrame.class.getName()).log(Level.SEVERE, null, ex);
panel_1.setLayout(new BorderLayout(0, 0));
panel_1.add(new JLabel(new ImageIcon(targetImg)));
setVisible(true);
private void browseButtonActionPerformed(java.awt.event.ActionEvent evt)
JFileChooser fc = new JFileChooser(basePath);
fc.setFileFilter(new JPEGImageFileFilter());
int res = fc.showOpenDialog(null);
// We have an image!
try
if (res == JFileChooser.APPROVE_OPTION)
File file = fc.getSelectedFile();
setTarget(file);
// Oops!
else
JOptionPane.showMessageDialog(null,
"You must select one image to be the reference.", "Aborting...",
JOptionPane.WARNING_MESSAGE);
catch (Exception iOException)
//JPEGImageFileFilter.java
package GUI;
import java.io.File;
import javax.swing.filechooser.FileFilter;
/*
* This class implements a generic file name filter that allows the listing/selection
* of JPEG files.
*/
public class JPEGImageFileFilter extends FileFilter implements java.io.FileFilter
public boolean accept(File f)
if (f.getName().toLowerCase().endsWith(".jpeg")) return true;
if (f.getName().toLowerCase().endsWith(".jpg")) return true;
if(f.isDirectory())return true;
return false;
public String getDescription()
return "JPEG files";
【问题讨论】:
@你能更新你的工作代码吗?? 1 额外建议,包名总是小写 【参考方案1】:每次选择新图像时,您都会在此处创建不必要且错误的组件:
public void setTarget(File reference)
//....
panel_1.setLayout(new BorderLayout(0, 0));
panel_1.add(new JLabel(new ImageIcon(targetImg)));
setVisible(true);
相反,我建议您在选择任何文件/图像之前从一开始就创建所有这些组件,然后在这个方法中,从图像创建一个 ImageIcon,然后简单地使用这个 Icon 来设置已经存在的 JLabel 而不是新的 JLabel 的图标。这只需调用myLabel.setIcon(new ImageIcon(targetImg));
【讨论】:
非常感谢您的回复:)它按您所说的那样工作。但是图像没有显示在中心。你能帮我吗...喜欢这个... label = new JLabel(); panel_1.add(标签); ..... label.setIcon(new ImageIcon(targetImg)); label.setHorizontalAlignment(SwingConstants.CENTER);使用了上面的线路,我明白了:)非常感谢您的帮助......@Hovercraft Full Of Eels @HovercraftFullOfEels ..在图像中设置第一次后无法工作?你能更新你的代码吗?【参考方案2】:使用ImageViewer.setImage(Image)
之类的方法创建ImageViewer
,将图像显示在JLabel
中。
图像查看器
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.util.Random;
public class ImageViewer
JPanel gui;
/** Displays the image. */
JLabel imageCanvas;
/** Set the image as icon of the image canvas (display it). */
public void setImage(Image image)
imageCanvas.setIcon(new ImageIcon(image));
public void initComponents()
if (gui==null)
gui = new JPanel(new BorderLayout());
gui.setBorder(new EmptyBorder(5,5,5,5));
imageCanvas = new JLabel();
JPanel imageCenter = new JPanel(new GridBagLayout());
imageCenter.add(imageCanvas);
JScrollPane imageScroll = new JScrollPane(imageCenter);
imageScroll.setPreferredSize(new Dimension(300,100));
gui.add(imageScroll, BorderLayout.CENTER);
public Container getGui()
initComponents();
return gui;
public static Image getRandomImage(Random random)
int w = 100 + random.nextInt(400);
int h = 50 + random.nextInt(200);
BufferedImage bi = new BufferedImage(
w,h,BufferedImage.TYPE_INT_RGB);
return bi;
public static void main(String[] args) throws Exception
Runnable r = new Runnable()
@Override
public void run()
JFrame f = new JFrame("Image Viewer");
// TODO Fix kludge to kill the Timer
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final ImageViewer viewer = new ImageViewer();
f.setContentPane(viewer.getGui());
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
ActionListener animate = new ActionListener()
Random random = new Random();
@Override
public void actionPerformed(ActionEvent arg0)
viewer.setImage(getRandomImage(random));
;
Timer timer = new Timer(1500,animate);
timer.start();
;
SwingUtilities.invokeLater(r);
【讨论】:
【参考方案3】:我修改了您的代码,希望它能满足您的要求。我使用 MigLayout(它是一个布局管理器)来排列组件。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics2D;
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.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
public class MyFileChooser
JFrame frame;
JPanel panel;
JButton btnBrowse;
JButton change;
JLabel imglabel;
File targetFile;
BufferedImage targetImg;
private static final int baseSize = 128;
private static final String basePath ="/images/fimage";
JPanel panel_1;
ImageIcon icon;
public MyFileChooser()
// TODO Auto-generated constructor stub
frame =new JFrame();
frame.setLayout(new MigLayout());
frame.setSize(300, 300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel=new JPanel(new MigLayout());
panel_1 = new JPanel();
panel_1.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(5, 5, 5), 1, true));
panel_1.setBackground(Color.pink);
btnBrowse=new JButton("browse");
btnBrowse.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent e)
browseButtonActionPerformed(e);
);
change=new JButton("Delete");
change.addActionListener(new ActionListener()
@Override
public void actionPerformed(ActionEvent e)
// TODO Auto-generated method stub
changeButtonActionPerformed(e);
private void changeButtonActionPerformed(ActionEvent e)
// TODO Auto-generated method stub
imglabel.revalidate(); //ADD THIS AS WELL
imglabel.repaint(); //ADD THIS AS WELL
imglabel.setIcon(null);
System.out.println("delete button activated");
);
imglabel=new JLabel("Image");
imglabel.setSize(100, 100);
imglabel.setBackground(Color.yellow);
frame.add(panel_1,"span,pushx,pushy,growx,growy");
frame.add(btnBrowse);
frame.add(change,"");
//frame.pack();
protected void browseButtonActionPerformed(ActionEvent e)
JFileChooser fc = new JFileChooser(basePath);
fc.setFileFilter(new JPEGImageFileFilter());
int res = fc.showOpenDialog(null);
// We have an image!
try
if (res == JFileChooser.APPROVE_OPTION)
File file = fc.getSelectedFile();
imglabel.setIcon(null);
setTarget(file);
// Oops!
else
JOptionPane.showMessageDialog(null,
"You must select one image to be the reference.", "Aborting...",
JOptionPane.WARNING_MESSAGE);
catch (Exception iOException)
public BufferedImage rescale(BufferedImage originalImage)
BufferedImage resizedImage = new BufferedImage(baseSize, baseSize, BufferedImage.TYPE_INT_RGB);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, baseSize, baseSize, null);
g.dispose();
return resizedImage;
public void setTarget(File reference)
try
targetFile = reference;
targetImg = rescale(ImageIO.read(reference));
catch (IOException ex)
// Logger.getLogger(MainAppFrame.class.getName()).log(Level.SEVERE, null, ex);
panel_1.setLayout(new BorderLayout(0, 0));
icon=new ImageIcon(targetImg);
imglabel=new JLabel(icon);
panel_1.add(imglabel);
frame.setVisible(true);
public static void main(String[] args)
SwingUtilities.invokeLater(new Runnable()
@Override
public void run()
// TODO Auto-generated method stub
new MyFileChooser();
);
JPEGImageFileFilter类,你可以把这个类放在同一个包里
import java.io.File;
import javax.swing.filechooser.FileFilter;
public class JPEGImageFileFilter extends FileFilter implements FileFilter
public boolean accept(File f)
if (f.getName().toLowerCase().endsWith(".jpeg")) return true;
if (f.getName().toLowerCase().endsWith(".jpg")) return true;
if(f.isDirectory())return true;
return false;
public String getDescription()
return "JPEG files";
【讨论】:
以上是关于浏览图像文件并使用 Java Swing 显示它的主要内容,如果未能解决你的问题,请参考以下文章
使用 java.awt 和 java.swing 获取要在框架上显示的 file.png 图像
如何在 Java Swing 应用程序的默认浏览器中打开 HTML 文件?