我无法以200的间隔更新图像

时间:2013-04-19 04:11:45

标签: java image jframe jpanel screen-capture

我正在尝试创建一个读取屏幕的线程并将其显示在一个框架中,此代码意味着以5fps运行,到目前为止,它读取屏幕,但我无法使JFrame显示更新的图像每个“框架”或200毫秒。当我使用repaint();或revalidate();

public static void startScreenRecorder() 
{
    Thread screenThread = new Thread()
    {
        public synchronized void run()
        {
            long time;
            long lastFrameTime = 0;
            JFrame frame = new JFrame("Screen capture");
            ImagePanel panel = new ImagePanel(captureScreen());
            frame.add(panel);
            frame.setSize(300, 400);
            frame.setVisible(true);

            while (true) 
            {
                time = System.currentTimeMillis();
                while (time - lastFrameTime < 190) 
                {
                    try {
                        Thread.sleep(10);
                    } catch (Exception e) {
                    }

                    time = System.currentTimeMillis();
                }                
                lastFrameTime = time;

                panel = new ImagePanel(captureScreen());
                panel.revalidate();
                panel.repaint();
                frame.revalidate();
                frame.repaint();
            }
        }
    };
    screenThread.start();
}

2 个答案:

答案 0 :(得分:2)

不要使用Thread.sleep()来尝试控制动画。

动画应该使用Swing Timer来完成。当您使用Timer时,GUI将在EDT上自动更新。

panel = new ImagePanel(captureScreen());

上面的代码没有做任何事情。它只是在内存中创建一个面板。无处你实际将面板添加到GUI。更改变量的引用不会更新GUI。

相反,您可能应该在框架中添加JLabel(最初创建框架时)。然后当你有一个新的图像时,你只需:

label.setIcon( new ImageIcon( your screen capture ) );

答案 1 :(得分:1)

如果您的代码完全没有显示图像,我会不会感到惊讶,因为它忽略了Swing线程规则:

  • 只需要在Swing事件调度线程(EDT)上调用所有Swing代码。
  • 需要在后台线程中调用所有其他长时间运行的代码。我认为这意味着captureScreen()
  • 除非您想让整个应用程序进入休眠状态,否则不应在Swing事件线程上调用Thread.sleep(...)
  • 最好也许使用Swing Timer。
  • 您创建新的ImagePanel但不对它们执行任何操作 - 例如,除了第一个JPanel之外,您永远不会将它们添加到GUI。请注意,如果更改变量引用的对象,这里是面板变量,这将对其他地方使用的对象的实例完全没有影响,在GUI中显示JPanel。
  • 与其创建新的JPanel,为什么不用图像创建ImageIcons并用setIcon(...)交换可视化的JLabel图标?
  • 由于您有很多背景资料,请考虑使用SwingWorker<Void, Icon>来完成您的工作,然后让它发布ImageIcons,然后将其显示在GUI的JLabel中。如果你这样做,那么你可能不会使用Swing Timer,因为时间将在SwingWorker的后台线程中完成。

例如:

import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

@SuppressWarnings("serial")
public class SwingWorkerEg extends JPanel {
   private static final int PREF_W = 600;
   private static final int PREF_H = 400;
   private JLabel displayedLabel = new JLabel();

   public SwingWorkerEg() {
      setLayout(new BorderLayout());
      add(displayedLabel);
      try {
         MySwingWorker mySwingWorker = new MySwingWorker();
         mySwingWorker.execute();
      } catch (AWTException e) {
         e.printStackTrace();
      }
   }

   public void setLabelIcon(Icon icon) {
      displayedLabel.setIcon(icon);
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   private class MySwingWorker extends SwingWorker<Void, Icon> {
      private final Rectangle SCREEN_RECT = new Rectangle(0, 0, PREF_W,
            PREF_H);
      private Robot robot = null;

      public MySwingWorker() throws AWTException {
         robot = new Robot();
      }

      @Override
      protected Void doInBackground() throws Exception {
         Timer utilTimer = new Timer();
         TimerTask task = new TimerTask() {

            @Override
            public void run() {
               BufferedImage capturedImage = captureScreen();
               publish(new ImageIcon(capturedImage));
            }

         };
         long delay = 200;
         utilTimer.scheduleAtFixedRate(task, delay, delay);
         return null;
      }

      @Override
      protected void process(List<Icon> chunks) {
         for (Icon icon : chunks) {
            setLabelIcon(icon);
         }
      }

      private BufferedImage captureScreen() {
         BufferedImage img = robot.createScreenCapture(SCREEN_RECT);
         return img;
      }

   }

   private static void createAndShowGui() {
      SwingWorkerEg mainPanel = new SwingWorkerEg();

      JFrame frame = new JFrame("SwingWorker Eg");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

哪个会显示......

enter image description here