【问题标题】:refreshing/reloading image in a Java Application (Swing)在 Java 应用程序(Swing)中刷新/重新加载图像
【发布时间】:2015-04-23 04:52:36
【问题描述】:

我已经编写了一个程序来从网络摄像头(通过 OpenCV)拍摄快照并将其保存到项目中:

Colordetection
|__src
|    |
|   main.java
|
| Snapshot.png

现在我想刷新拍摄的快照,每次我重新拍摄并重新绘制它。

String imgText = "Snapshot.png";

JPanel panelScreenshot = new JPanel();
panelScreenshot.setBorder(new TitledBorder(null, "Screenshot", TitledBorder.LEADING, TitledBorder.TOP, null, null));
panelScreenshot.setBounds(10, 11, 667, 543);
panelDisplay.add(panelScreenshot);
panelScreenshot.setLayout(null);

JLabel lblScreenshot = new JLabel();
lblScreenshot.setIcon(new ImageIcon(imgText));
lblScreenshot.setBounds(10, 21, 640, 480);
panelScreenshot.add(lblScreenshot);

JButton btnScreenshot = new JButton("Screenshot");
btnScreenshot.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent e) {              


    VideoCapture cap = new VideoCapture(0);

    if(!cap.isOpened()){
      System.out.println("Webcam not Found");

      } 
      else 
      {
      System.out.println("Found Webcam:" + cap.toString());

      Mat frame = new Mat();
      cap.retrieve(frame);

      try {
          Thread.sleep(500);
          Highgui.imwrite("Snapshot.png", frame);

          lblScreenshot.repaint();                  

          } 
          catch (Exception e1) {
            e1.printStackTrace();

      }
      cap.release();                    
    }       
  }
});

问题是,它不会像我想要的那样重新绘制/刷新,只有当我重新启动程序时,新的屏幕截图才会出现。

我也试过了:

ImageIcon icon = new ImageIcon(main.class.getResource("Snapshot.png"));

并更改了路径等,但没有帮助。

有人知道吗?

谢谢。

【问题讨论】:

    标签: java image swing refresh repaint


    【解决方案1】:

    图像由 ImageIcon 缓存,因此您可以:

    1. 刷新图像,强制重新加载
    2. 使用 ImageIO 重新读取图像

    简单示例:

    import java.awt.*;
    import java.awt.event.*;
    import java.awt.image.*;
    import java.io.*;
    import java.util.*;
    import javax.imageio.*;
    import javax.swing.*;
    import java.net.*;
    
    public class ImageReload extends JPanel implements ActionListener
    {
        JLabel timeLabel;
        JLabel imageLabel;
        ImageIcon icon = new ImageIcon("timeLabel.jpg");
    
        public ImageReload()
        {
            setLayout( new BorderLayout() );
    
            timeLabel = new JLabel( new Date().toString() );
            imageLabel = new JLabel( timeLabel.getText() );
    
            add(timeLabel, BorderLayout.NORTH);
            add(imageLabel, BorderLayout.SOUTH);
    
            javax.swing.Timer timer = new javax.swing.Timer(1000, this);
            timer.start();
        }
    
        public void actionPerformed(ActionEvent e)
        {
            timeLabel.setText( new Date().toString() );
    
            SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    try
                    {
                        String imageName = "timeLabel.jpg";
                        BufferedImage image = ScreenImage.createImage(timeLabel);
                        ScreenImage.writeImage(image, imageName);
    
                        //  This works using ImageIO
    
    //                  imageLabel.setIcon( new ImageIcon(ImageIO.read( new File(imageName) ) ) );
    
                        //  Or you can flush the image
    
                        ImageIcon icon = new ImageIcon(imageName);
                        icon.getImage().flush();
                        imageLabel.setIcon( icon );
                    }
                    catch(Exception e)
                    {
                        System.out.println( e );
                    }
                }
            });
        }
    
        private static void createAndShowUI()
        {
            JFrame frame = new JFrame("SSCCE");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add( new ImageReload() );
            frame.setLocationByPlatform( true );
            frame.pack();
            frame.setVisible( true );
        }
    
        public static void main(String[] args)
        {
            EventQueue.invokeLater(new Runnable()
            {
                public void run()
                {
                    createAndShowUI();
                }
            });
        }
    }
    

    此示例还需要Screen Image 类来动态重新生成图像。

    【讨论】:

      【解决方案2】:

      永远不要在 EDT 上致电 Thread.sleep。这会冻结你的整个 UI。 Swing 是单线程的,所以如果你让那个线程休眠,整个 UI 就会被冻结

      话虽如此,原因是图标只加载一次。磁盘上的实际映像发生变化并不重要。你需要打电话

      lblScreenshot.setIcon(new ImageIcon(imgText));
      

      在您更换光盘上的映像后再次。这将重新加载图像。

      【讨论】:

      • 感谢您的回答,我删除了 Thread.sleep 并在重绘前添加了lblScreenshot.setIcon(new ImageIcon(imgText));。但它没有改变。
      猜你喜欢
      • 2015-11-16
      • 2015-02-11
      • 2019-04-05
      • 2011-06-21
      • 2014-09-08
      • 2014-02-14
      • 1970-01-01
      • 2023-04-07
      • 2011-01-07
      相关资源
      最近更新 更多