2013-07-24 35 views
-2

我想要以JFrame的形式加载图像,使其看起来像是视频。
更改图像,如看起来像视频

对于我以为我会改变的图像,以便更快(20张/秒)。

,但问题是,当新的图像获取加载其显示全黑的窗口。
我不知道为什么会发生。
建议我在哪里出错了。

import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Image; 
import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import java.io.*; 
import javax.imageio.ImageIO; 

class VideoI extends JPanel { 

    private Image img; 
    private Graphics graphics; 
    ImageIcon icon; 

    VideoI(){ 
    icon=new ImageIcon("D:\\Videos\\1.jpg"); 
     add(icon); 
    } 

     public void paintComponent(Graphics g) { 
     graphics=g; 
     repeatImgs(); 
     } 

     public void repeatImgs(){ 
     for(int i=0;i<25;i++) 
     { try{ 
      img=ImageIO.read(new File("D:\\Videos\\"+i+".jpg")); 
      graphics.drawImage(img, 0, 0, null); 
      System.out.println(""+i); 
      Thread.sleep(1000); 
      }catch(Exception e){System.out.println(""+i+":"+e);} 
     } 


     } 

    } 

public class Video extends JFrame 
{ 
public static void main(String args[]) 
{ 
    new Video().start(); 
} 

public void start() 
{ 
    VideoI panel = new VideoI(); 

    add(panel); 

     setVisible(true); 

     setSize(1300,800); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 

} 
    } 
+1

1)不要阻塞EDT(Event Dispatch Thread) - 当发生这种情况时GUI将“冻结”。而不是调用'Thread.sleep(n)'实现一个Swing'Timer'来重复执行任务,或者一个'SwingWorker'执行长时间运行的任务。有关更多详细信息,请参见[Swing中的并发](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/)。 2)不要试图加载循环中的图像。 3)'graphics.drawImage(img,0,0,null);'应该是'graphics.drawImage(img,0,0,this);'4)对代码块使用一致的逻辑缩进。代码的缩进旨在帮助人们理解流程。 –

+0

对不起,因为我写错了代码。
我没有得到你的第二点。你能建议我可以做什么,而不是使用for循环? –

+0

对点2的修复基本上是在构造函数中加载图像,并简单地将它们保存在数组或类似结构中。 –

回答

1

您正在阻止事件分派线程。使用挥杆Timer以所需的频率重新绘制组件。

你永远不应该在美国东部时间sleep()。你想要什么本质上是

public void paintComponent(Graphics g) { 
    // No loops or delays, just fetch the next image, preferrably it has been 
    // already been loaded by another thread. 
    g.drawImage(getNextImage(), 0, 0, null); 
} 

和计时器任务:

ActionListener timerTask = new ActionListener() { 
    @Override 
    public void actionPerformed(final ActionEvent e) { 
     panel.repaint(); 
    } 
}; 

Timer timer = new Timer(50, timerTask); 

当你要开始视频,只需调用timer.start()

最后,您还应该使用SwingUtilities.invokeLater()来包装创建GUI。

+0

我应该在哪里使用? (定时器计时器=新的计时器();)在主要方法或在我的JFrame .. &我需要添加ActionListernr ??? –

+0

“定时器”声明可以转到多个不同的地方,具体取决于应用程序的设计。例如,它可以是视频类的一个领域。为了快速测试,你可以把它放在你的'start()'方法中。 'ActionListener'是'Timer'每50ms执行一次的任务,不用担心接口名称。 – kiheru

+0

谢谢。它帮助我很多。我试试看,如果它不会工作,我会再次问你的帮助。 –

1

您正在发送事件调度线程(UI更新线程)进入睡眠状态,这就是为什么您会遇到屏幕问题。 尝试在工作线程中加载和切换图像(查看JavaDoc的SwingWorker)。

1

我不是Swing的期待,但我想这会发生,因为你停止与Thread.sleep Swing线程。您应该在摆动线外进行图像更改和定时,并使用SwingUtilities.invokeLater来绘制图像。你也需要睡50ms,而不是20fps的整秒。在这里使用ScheduledExecutorService

此外,您总是从光盘加载图像,当它需要被渲染。这可能会变慢。最好在启动时加载所有图像,然后更改图像。

+0

谢谢。现在我得到一些击球手的想法。但是,请你告诉我如何在启动时加载所有图像。我仍然认为它会在我的应用程序上制造更多的burdon。不是吗? –

+0

Just和另一个用于将所有图像(1.jpg - 25.jpg)放入列表中的循环。显示图像时访问列表。您将需要更多的内存,因为图像存储在内存中。但是否则,图像加载可能会减慢从光盘每秒钟加载20个图像。 – ssindelar

+0

我想它会使用很多内存(因为我的所有图像都是100kb的atlist)。 –