在 bufferedImage 上绘制时闪烁

Flickering when drawing onto bufferedImage

我有一个 3d 对象,它由我使用 graphics2D 绘制的多个多边形组成。当我旋转它时,似乎没有足够的时间在每一帧绘制整个对象,因为在某些帧,一些多边形只是丢失(未绘制)。我不明白这是怎么回事,因为我在 paintComponent 中首先将所有多边形绘制到 bufferedImage myImg 上,然后将完成的图像绘制到屏幕上。当我删除 clearRect 时,此问题得到解决,但当然它不会在绘制下一帧之前删除最后一帧的绘图。

注意:我是一个业余爱好者,但我已经非常努力地理解了,所以这是我最后的选择,我很乐意得到一些帮助。代码(去掉不必要的代码如下):

 public class Main {

       long temp = System.currentTimeMillis() + frameRate;

       public static void main(String[] args) {
          myGUI = new GUI(width, height);       
          while(true) {
            if (System.currentTimeMillis() >= temp) {
              temp += frameRate;
              rotateObject();
              myGUI.myCanvas.myLabel.repaint();
            }
          }
       }
    }
    
    public class GUI extends JFrame {
        
        public Canvas myCanvas;
    
        public GUI(int w, int h) {
           this.setSize(w, h);
           this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    
           myCanvas = new Canvas(w, h);
           this.getContentPane().add(myCanvas);
           this.setVisible(true);
           this.pack();
        }
    }

    public class Canvas extends JPanel {
    
      public BufferedImage myImg;
      public Graphics2D g2d;
      public JLabel myLabel;
    
      public Canvas(int w, int h) {
          myImg = new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR);
          myLabel = new JLabel(new ImageIcon(myImg));
          this.add(myLabel);
          g2d = myImg.createGraphics();
      }

      @Override
      public void paintComponent(Graphics g) {
          super.paintComponent(g);
          g2d.clearRect(0, 0, myImg.getWidth(), myImg.getHeight());
          g2d.setColor(Color.RED));
          g2d.fillPolygon(pointsX, pointsY, 3);
          g.drawImage(myImg, 0, 0, null);
      }
    }

This is how my object is flickering

你真的需要花时间通读:

这些不是“初学者”主题,对一般的 Swing 和特定的语言有合理的理解将非常有利。

永远不要在组件上使用 getGraphics。这简直是​​个坏主意(我不知道为什么这个方法是 public)。

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    JFrame frame = new JFrame();
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage myImg;
        private double rotation;

        public TestPane() throws IOException {
            myImg = ImageIO.read(getClass().getResource("/images/happy.png"));

            Timer timer = new Timer(33, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    rotation += Math.toRadians(5);
                    repaint();
                }
            });
            timer.start();
        }

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

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            AffineTransform at = AffineTransform.getTranslateInstance((getWidth() - myImg.getWidth()) / 2, (getHeight() - myImg.getHeight()) / 2);
            at.rotate(rotation, myImg.getWidth() / 2, myImg.getHeight() / 2);

            g2d.transform(at);
            g2d.drawImage(myImg, 0, 0, this);
            g2d.dispose();
        }
    }
}