【问题标题】:Java GUI: Image will be overwritten, Path the same -> show it in the frame (image still the same)Java GUI:图像将被覆盖,路径相同->在框架中显示(图像仍然相同)
【发布时间】:2014-05-17 00:44:36
【问题描述】:

我想在我的框架上显示一个不断变化的图像。图像路径始终相同,但图像将每 10 秒被另一个程序覆盖一次。 问题是图像在我用另一个具有同名的图像覆盖时没有改变。所以在我的理解中:编译器会查看路径中的每一个外观并获取图像 -> 当图像更改时,它将在框架上更改!

我希望你能理解我的问题并且有人可以帮助我。

    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.GridLayout;
    import java.io.File; 

    import javax.swing.ImageIcon;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;

    public class GUI extends JFrame{

        public ImageIcon imageBar;

        public JLabel labelimage1;
        private JLabel labelimage2;

        private JLabel bar1 = new JLabel();
        private JLabel bar2 = new JLabel();
        private JLabel bar3 = new JLabel();
        private JLabel bar4 = new JLabel();
        private JLabel bar5 = new JLabel();

        private JButton buttonBar1 = new JButton("1");
        private JButton buttonBar2 = new JButton("2");
        private JButton buttonBar3 = new JButton("3");
        private JButton buttonBar4 = new JButton("4");
        private JButton buttonBar5 = new JButton("5");

        private JPanel panel1 = new JPanel();
        private JPanel panel2 = new JPanel();
        private JPanel panel3 = new JPanel();

        private JFrame window = new JFrame("Interface");

        public GUI(){

            //set the layouts
            panel1.setLayout(new GridLayout(1, 2)); 
            panel2.setLayout(new GridLayout(2, 1));
            panel3.setLayout(new GridLayout(2, 5));

            //place Panel2 and Panel3 in the window
            panel1.add(panel2); 
            panel1.add(panel3);

            //----Panel2
            //refreshImage();


            //----Panel3        
            panel3.add(buttonBar1); //add the bars 1-5 on panel3
            panel3.add(buttonBar2);
            panel3.add(buttonBar3);
            panel3.add(buttonBar4);
            panel3.add(buttonBar5);

            //configure the frame
            window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            window.setVisible(true);
            window.setSize(800, 400);
            window.getContentPane().add(panel1);
        }


        public void refreshImage() {

            panel2.removeAll(); //delete the old panel
            //panel2.repaint();
            //panel2.revalidate()

            DrawImage pan = new DrawImage();

            panel2.add(pan);
            panel2.add(labelimage2);
        }
}


import javax.swing.ImageIcon;
import javax.swing.JPanel;


public class DrawImage extends JPanel implements ActionListener{

    private ImageIcon image;

    public DrawImage(){
        image = new ImageIcon("C:\\Users\\usuario\\Desktop\\image.png");
    }

    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        image.paintIcon(this, g, 50, 50);
        repaint();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        repaint();
    }

}

import java.io.File;

public class Main {

    public static void main(String[] args) {

        GUI Interface = new GUI(); 

        while(true)
        {
            Interface.refreshImage(); 
            try {
                        Thread.sleep(5000); //wait for 5000ms
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
        }

    }

}

非常感谢!

【问题讨论】:

    标签: java image swing user-interface filepath


    【解决方案1】:

    可能的原因是 Java 将图像缓存在内存中,并与源名称相关联。因此,Java 不再尝试重新加载图像,而是简单地返回缓存的版本。

    您可以使用ImageIcon#getImage#flush 强制Java 重建图像

    问题

    • 您正在从 Thread 以外的事件调度线程调用 refreshImage,这可能会导致组件更新出现问题并导致呈现工件
    • 您正在强行删除 DrawImage 窗格并添加新实例,而不是尝试重新加载图像
    • 您在paintComponent 方法中调用repaint,不要这样做...

    您应该考虑使用Swing Timer,这将允许您安排定期更新并在事件调度线程的上下文中收到通知。

    您可以提供一个简单的 refresh 方法来刷新当前的 ImageIcon 并安排重新绘制面板...或者您可以只使用 JLabel 并节省您自己的时间

    Image#flush的一个例子

    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.ImageIcon;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class SlideShow {
    
        public ImageIcon imageBar;
    
        public static void main(String[] args) {
            new SlideShow();
        }
    
        public SlideShow() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
                    frame.add(new DrawImage());
    
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class DrawImage extends JPanel {
    
            private ImageIcon image;
    
            public DrawImage() {
                image = new ImageIcon("D:\\thumbs\\image.png");
                Timer timer = new Timer(5000, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        refresh();
                    }
                });
                timer.start();
            }
    
            public void refresh() {
                image.getImage().flush();
                repaint();
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.drawImage(image.getImage(), 0, 0, this);
            }
    
        }
    }
    

    这样做的问题是,由于图像数据是在后台线程中加载的,在组件第一次重绘时可能不可用,这可能会使组件看起来闪烁。

    更好的方法是使用ImageIO.read,这将确保图像在方法返回之前完全加载,这里的缺点是可能导致应用程序在图像加载时暂时“暂停”,个人,我会使用refresh方法停止Timer(或将Timer设置为非重复),启动背景Thread来加载图像(使用ImageIO.read)调用repaint (这是线程安全的)并重新启动Timer...

    【讨论】:

      【解决方案2】:
      1. 您的while (true) 循环可能会键入锁定您的程序的Swing 事件线程。如果它不这样做,那么您可能会通过从事件线程中调用 Swing 来冒不可预测的线程问题。通过使用 Swing Timer 而不是 while true 循环来进行交换,可以轻松解决这些问题。
      2. 与其删除和添加组件,不如简单地将图像显示为单个非交换 JLabel 中的 ImageIcon。
      3. 要在此处交换图像,只需在 JLabel 上调用 setIcon(...)。

      有关使用 Swing Timer 交换图像的示例,请查看我对类似问题的回答 here。


      例如:

      import java.awt.Component;
      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;
      import java.awt.image.BufferedImage;
      import java.io.IOException;
      import java.net.URL;
      
      import javax.imageio.ImageIO;
      import javax.swing.*;
      
      public class TimerImageSwapper {
         public static final String[] IMAGE_URLS = {
               "http://imaging.nikon.com/lineup/dslr/d7000/img/sample/img_01.png",
               "http://imaging.nikon.com/lineup/dslr/d7000/img/sample/img_02.png",
               "http://imaging.nikon.com/lineup/dslr/d7000/img/sample/img_04.png",
               "http://imaging.nikon.com/lineup/dslr/d3200/img/sample/img_08.png",
               "http://imaging.nikon.com/lineup/dslr/d3200/img/sample/img_05.png",
               "http://imaging.nikon.com/lineup/dslr/d3200/img/sample/img_01.png",
               "http://imaging.nikon.com/lineup/dslr/d3200/img/sample/img_06.png" };
      
      
         private ImageIcon[] icons = new ImageIcon[IMAGE_URLS.length];
         private JLabel mainLabel = new JLabel();
      
         private int iconIndex = 0;;
      
         public TimerImageSwapper(int timerDelay) throws IOException {
            for (int i = 0; i < icons.length; i++) {
               URL imgUrl = new URL(IMAGE_URLS[i]);
               BufferedImage image = ImageIO.read(imgUrl);
               icons[i] = new ImageIcon(image);
            }
      
            mainLabel.setIcon(icons[iconIndex]);
      
            new Timer(timerDelay, new ActionListener() {
      
               @Override
               public void actionPerformed(ActionEvent arg0) {
                  iconIndex++;
                  iconIndex %= IMAGE_URLS.length;
                  mainLabel.setIcon(icons[iconIndex]);
               }
            }).start();
         }
      
         public Component getMainComponent() {
            return mainLabel;
         }
      
         private static void createAndShowGui() {
            TimerImageSwapper timerImageSwapper;
            try {
               timerImageSwapper = new TimerImageSwapper(5 * 1000);
               JFrame frame = new JFrame("Timer Image Swapper");
               frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
               frame.getContentPane().add(timerImageSwapper.getMainComponent());
               frame.pack();
               frame.setLocationByPlatform(true);
               frame.setVisible(true);
      
            } catch (IOException e) {
               e.printStackTrace();
               System.exit(-1);
            }
      
         }
      
         public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
               public void run() {
                  createAndShowGui();
               }
            });
         }
      }
      

      【讨论】:

        猜你喜欢
        • 2021-02-04
        • 2015-12-11
        • 2011-05-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-23
        • 2019-08-31
        • 1970-01-01
        相关资源
        最近更新 更多