我想在我的相框上显示变化的图像。图像路径始终相同,但图像每 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 将与源名称关联的图像缓存在内存中。因此,Java 只是返回缓存的版本,而不是尝试再次重新加载图像。
您可以使用ImageIcon#getImage#flush
强制Java重建图像
问题
- 您正在从事件调度线程以外的
线程
调用refreshImage
,这可能会导致组件更新出现问题并导致渲染伪影 - 您正在强制删除
DrawImage
Pane 并添加新实例,而不是尝试重新加载图像 - 您正在
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
,这将确保在方法返回之前完全加载图像,这里的缺点是可能会导致应用程序暂时“暂停”当图像加载时,就我个人而言,我会使用刷新方法来停止计时器(或将计时器设置为不重复) ),启动一个后台Thread
来加载图像(使用ImageIO.read
)调用repaint
(这是线程安全的)并重新启动计时器
...
关于Java GUI : Image will be overwritten, 路径相同 -> 在框架中显示它(图像仍然相同),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23706492/