使用JLabels更新图像的正确方法

我正在创建一个GUI,并且是一个相当新的摇摆和awt。 我正在尝试创建一个gui,在启动时,将背景设置为图像,然后使用方法创建各种幻灯片。 我已经尝试过,而且我没有附加到代码中,所以我能够同时修改和/或全新的概念。

编辑(2013年9月15日):我在播放幻灯片时遇到问题,似乎无法让它发挥作用。

这是我目前的代码。

public class MainFrame extends JFrame{ JLabel backgroundL = null; private JLabel bakckgroundL; BufferedImage backimg; Boolean busy; double width; double height; public MainFrame() throws IOException { initMainframe(); } public void initMainframe() throws IOException { //misc setup code, loads a default jpg as background setTitle("Pemin's Aura"); busy = true; String backgroundDir = "resources/frame/background.jpg"; backimg = ImageIO.read(new File(backgroundDir)); backgroundL = new JLabel(new ImageIcon(backimg)); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); refreshframe(); setVisible(true); busy = false; } public void adjSize() { // the attempted start of a fullscreen mode GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(this); width = this.getWidth(); height = this.getHeight(); setVisible(true); } public void setmastheadText() {//unfinished code busy = true; busy = false; } public void setbackground() { add(backgroundL); } public void refreshframe() { //should refresh image? setSize(2049, 2049); setSize(2048, 2048); } public void loadingscreen() throws IOException, InterruptedException { //this is the code in question that is faulty. if (busy == false) { busy = true; String backgroundDir1 = "resources/frame/background.jpg"; String backgroundDir2 = "resources/frame/scr1.jpg"; String backgroundDir3 = "resources/frame/scr2.jpg"; BufferedImage backimg1 = ImageIO.read(new File(backgroundDir1)); BufferedImage backimg2 = ImageIO.read(new File(backgroundDir2)); BufferedImage backimg3 = ImageIO.read(new File(backgroundDir3)); backgroundL = new JLabel(new ImageIcon(backimg1)); Thread.sleep(2000); setbackground(); setVisible(true); backgroundL = new JLabel(new ImageIcon(backimg2)); setbackground(); setVisible(true); Thread.sleep(2000); bakckgroundL = new JLabel(new ImageIcon(backimg3)); setbackground(); setVisible(true); if(backimg != null) { backgroundL = new JLabel(new ImageIcon(backimg));; } } busy = false; }//end of loading screen 

有关使用基于Swing的Timer显示图像的工作示例,请参阅ImageViewer

另请参见如何使用Swing Timers 。


虽然我在这里,另一个(更漂亮)动画图像的例子。 它使用了墨卡托土地质量图。 图像可以水平平铺,因此可以根据需要向左/向右滚动。

墨西哥土地集团地图

 import java.awt.*; import java.awt.event.*; import java.awt.geom.Point2D; import java.awt.image.BufferedImage; import javax.swing.*; import java.net.URL; import javax.imageio.ImageIO; public class WorldView { public static void main(String[] args) throws Exception { URL url = new URL("http://i.stack.imgur.com/P59NF.png"); final BufferedImage bi = ImageIO.read(url); Runnable r = new Runnable() { @Override public void run() { int width = 640; int height = 316; Graphics2D g = bi.createGraphics(); float[] floats = new float[]{0f, .4f, .55f, 1f}; Color[] colors = new Color[]{ new Color(20, 20, 20, 0), new Color(0, 10, 20, 41), new Color(0, 10, 20, 207), new Color(0, 10, 20, 230),}; final LinearGradientPaint gp2 = new LinearGradientPaint( new Point2D.Double(320f, 0f), new Point2D.Double(0f, 0f), floats, colors, MultipleGradientPaint.CycleMethod.REFLECT); final BufferedImage canvas = new BufferedImage( bi.getWidth(), bi.getHeight() + 60, BufferedImage.TYPE_INT_RGB); final JLabel animationLabel = new JLabel(new ImageIcon(canvas)); ActionListener animator = new ActionListener() { int x = 0; int y = 30; @Override public void actionPerformed(ActionEvent e) { Graphics2D g = canvas.createGraphics(); g.setColor(new Color(55, 75, 125)); g.fillRect(0, 0, canvas.getWidth(), canvas.getHeight()); int offset = (x % bi.getWidth()); g.drawImage(bi, offset, y, null); g.drawImage(bi, offset - bi.getWidth(), y, null); g.setPaint(gp2); g.fillRect(0, 0, canvas.getWidth(), canvas.getHeight()); g.dispose(); animationLabel.repaint(); x++; } }; Timer timer = new Timer(40, animator); timer.start(); JOptionPane.showMessageDialog(null, animationLabel); timer.stop(); } }; // Swing GUIs should be created and updated on the EDT // http://docs.oracle.com/javase/tutorial/uiswing/concurrency SwingUtilities.invokeLater(r); } } 

这是添加了赤道的图像的一个版本(它是图像中心的“南”44像素)。

在此处输入图像描述

你正在调用Thread.sleep(...)并且可能在EDT或Swing事件线程上(全名是E vent D ispatch T hread)。 该线程负责所有Swing绘画/绘图和用户交互,因此hibernate它只会冻结整个GUI。 相反,您应该使用Swing Timer来交换JLabel的ImageIcon。

简而言之:

  • 不要在Swing事件线程(Event Dispatch Thread或EDT)上调用Thread.sleep(...) )。
  • 使用Swing Timer进行重复延迟操作。
  • 不要制作和添加许多JLabel。 只需制作并添加一个。
  • 通过调用标签上的setIcon(...)来交换JLabel显示的ImageIcon。
  • 更好(更清洁)写if (busy == false) { if (!busy) {

例如,

 ImageIcon[] icons = {...}; // filled up with your ImageIcons if (!busy) { int timerDelay = 2000; new Timer(timerDelay, new ActionListener() { private int i = 0; public void actionPerfomed(ActionEvent e) { myLabel.setIcon(icons(i)); i++; if (i == icons.length) { ((Timer)e.getSource).stop(); } }; }).start(); }