在JPanel中绘制捕获的屏幕图像,图像再次显示一次,我如何修复它显示一次?



我想从屏幕上捕获图像并在JPanel中绘制它,它工作,但它再次显示一次,就像进入循环一样,我对此感到困惑,我该如何修复它,请?变量Iwidth, iheight在上面初始化了,但是我取了导致问题的代码块

 protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Image img;            
         ImageIcon i = null;            
        Rectangle screenRect=new     Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
         try {
             BufferedImage capture=new Robot().createScreenCapture(screenRect);
             capture.getHeight();
             capture.getWidth();
             i=new ImageIcon(capture);
         } catch (AWTException ex) {
             Logger.getLogger(TestDrawing.class.getName()).log(Level.SEVERE, null, ex);
         }
         img = i.getImage();
         g.drawImage(img,Iwidth,Ihieght,null);
         super.repaint();
  }

永远不要在paintComponent中使用这样的代码。该方法应该只用于绘制和绘制,并且是一个您无法完全控制的方法,因为它是由JVM调用的,以响应您的请求和来自操作系统的请求,即使您请求重新绘制,也不能保证它将被遵守,特别是当请求堆积时。此外,GUI的感知响应性通常取决于绘制完成的速度,而文件读取和图像捕获永远不应该在paintComponent中完成。

相反,您应该读取图像作为对某些事件的反应,可能是计时器,然后在读取图像后,调用repaint()并在paintComponent中绘制获得的图像。

也不要在paintComponent内部调用repaint()

类似于伪代码

// inside of the ActionListener of a Swing Timer (if you want to do this repeatedly)
get screen image from robot and feed it into the capture BufferedImage field
consider doing this in a SwingWorker
call repaint() when SwingWorker is done (via a PropertyChangeListener)

Inside of paintComponent:

@Override
protected void paintComponent(Graphics g) {
   super.paintComponent(g);
   if (capture != null) {
      g.drawImage(capture, capture.getWidth(), capture.getHeight());
   }
}

编辑

例如:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
import javax.swing.SwingWorker.StateValue;
public class ScreenCaptureTest extends JPanel {
   private static final int PREF_W = 600;
   private static final int PREF_H = 400;
   private JButton btn = new JButton(new ScreenCaptureAction(this,
         "Capture Screen", KeyEvent.VK_C));
   private ImagePanel imagePanel = new ImagePanel();
   public ScreenCaptureTest() {
      JPanel buttonPanel = new JPanel();
      buttonPanel.add(btn);
      setLayout(new BorderLayout());
      add(new JScrollPane(imagePanel), BorderLayout.CENTER);
      add(buttonPanel, BorderLayout.SOUTH);
   }
   public void setImagePanelImage(BufferedImage img) {
      imagePanel.setImage(img);
      revalidate();
      repaint();
   }
   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }
   private static void createAndShowGui() {
      ScreenCaptureTest mainPanel = new ScreenCaptureTest();
      JFrame frame = new JFrame("ScreenCaptureTest");
      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();
         }
      });
   }
}
class ImagePanel extends JPanel {
   private BufferedImage image;
   public void setImage(BufferedImage image) {
      this.image = image;
      revalidate();
      repaint();
   }
   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (image != null) {
         g.drawImage(image, 0, 0, null);
      }
   }
   @Override
   public Dimension getPreferredSize() {
      if (image != null) {
         return new Dimension(image.getWidth(), image.getHeight());
      }
      return super.getPreferredSize();
   }
}
class ScreenCaptureAction extends AbstractAction {
   private ScreenCaptureTest screenCaptureTest;
   public ScreenCaptureAction(ScreenCaptureTest screenCaptureTest, String name,
         int mnemonic) {
      super(name);
      putValue(MNEMONIC_KEY, mnemonic);
      this.screenCaptureTest = screenCaptureTest;
   }
   @Override
   public void actionPerformed(ActionEvent e) {
      setEnabled(false);
      final SwingWorker<BufferedImage, Void> mySwingWorker = new SwingWorker<BufferedImage, Void>() {
         @Override
         protected BufferedImage doInBackground() throws Exception {
            Toolkit toolkit = Toolkit.getDefaultToolkit();
            Dimension screenSize = toolkit.getScreenSize();
            Robot robot = new Robot();
            BufferedImage capture = robot.createScreenCapture(new Rectangle(
                  screenSize));
            return capture;
         }
      };
      mySwingWorker.addPropertyChangeListener(new PropertyChangeListener() {
         @Override
         public void propertyChange(PropertyChangeEvent pcEvt) {
            if ("state".equals(pcEvt.getPropertyName())
                  && pcEvt.getNewValue() == StateValue.DONE) {
               setEnabled(true);
               try {
                  screenCaptureTest.setImagePanelImage(mySwingWorker.get());
               } catch (InterruptedException | ExecutionException e) {
                  e.printStackTrace();
               }
            }
         }
      });
      mySwingWorker.execute();
   }
}

编辑
注意,如果这是我的程序,我会在JLabel中将图像显示为ImageIcon,因为这样编写代码要简单得多。然后你可以去掉ImagePanel类和它的paintComponent方法,并简单地将main代码为:

public class ScreenCaptureTest extends JPanel {
   private static final int PREF_W = 600;
   private static final int PREF_H = 400;
   private JButton btn = new JButton(new ScreenCaptureAction(this,
         "Capture Screen", KeyEvent.VK_C));
   //!! private ImagePanel imagePanel = new ImagePanel();
   private JLabel screenLabel = new JLabel(); //!!
   public ScreenCaptureTest() {
      JPanel buttonPanel = new JPanel();
      buttonPanel.add(btn);
      setLayout(new BorderLayout());
      //!! add(new JScrollPane(imagePanel), BorderLayout.CENTER);
      add(new JScrollPane(screenLabel), BorderLayout.CENTER); //!! 
      add(buttonPanel, BorderLayout.SOUTH);
   }
   public void setImagePanelImage(BufferedImage img) {
      //!! imagePanel.setImage(img);
      Icon icon = new ImageIcon(img);
      screenLabel.setIcon(icon);
//!!      revalidate();
//!!      repaint();
   }
   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }
   private static void createAndShowGui() {
      ScreenCaptureTest mainPanel = new ScreenCaptureTest();
      JFrame frame = new JFrame("ScreenCaptureTest");
      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();
         }
      });
   }
}

最新更新