repaint()的绘制速度比paintComponent()慢吗? [英] repaint() paints slower than paintComponent()?

查看:132
本文介绍了repaint()的绘制速度比paintComponent()慢吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在绘画使用paintComponent()定义的车辆对象. 因为车辆可以移动,所以我实现了ActionListener并设置了一个Timer()进行触发.

I am painting vehicle objects that I defined using the paintComponent(). Because the vehicles can move, I implement ActionListener and set a Timer() to trigger.

结果,我的车辆可以行驶.但这有点动摇".当我继续调整窗口大小以调用paintComponent()时,移动变得平滑.当我不调整窗口大小(不调用paintComponent)时,它再次变得肮脏.为什么?如何解决?

As a result, my vehicles can move. But it is kind of "shaking". When I keep resizing the window to call the paintComponent(), the movement becomes smooth. When I do not resize the window (not calling paintComponent), it gets skaking again. Why? How to fix it?

public class VehiclesComponent extends JComponent implements ActionListener{
    private Vehicle[] vehicles;
    private Timer timer;

    public VehiclesComponent(int n){
        vehicles = Vehicle.generateVehicle(n);
        timer = new Timer(5,this);
    } 

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;

        for (int i=0; i<vehicles.length; i++) {
            vehicles[i].draw(g2);
        }

        // may change later
        timer.start();
    }

    @Override
    public void actionPerformed(ActionEvent e){

        //check collision in here
        for (Vehicle v : vehicles) {
            if (Vehicle.intersectsOther(v, vehicles)) {
                v.collisionSideEffect();
            }
        }

        //move all in here

        for (Vehicle v : vehicles ) {
            v.move();
        }

        repaint(); 
        //?? repaint slower than paintComponent
    }


} 

推荐答案

首先查看

Start by taking a look at Painting in AWT and Swing. Remember, repaint is only a suggest made to the RepaintManager, the RepaintManager may choose to consolidate multiple repaint calls into a smaller number of actual paint events.

请确保您正在呼叫super.paintComponent,否则您将无止境地出现奇怪的绘画伪像.

Make sure you are calling super.paintComponent, otherwise you will end up with no end of strange paint artifacts.

请勿在任何绘制方法中直接或间接地修改组件或其他组件的状态,这将导致发出新的repaint请求,这可能导致绘制事件的循环可能会消耗您的CPU周期.这意味着不要呼叫timer.start()

Don't, directly or indirectly, modify the state of the component or ant other components from within any paint method, this will result in a new repaint request been made, which could lead to a cycle of paint events which could consume your CPU cycles. This means, don't call timer.start()!

没有一个可操作的例子,我一起努力.现在这可以动画10 000个单独的Vehicle s(矩形),因此它的杀伤力很大,但是它应该提供要点...

Without a runable example to go by, I hobbled this together. Now this is animating 10, 000 individual Vehicles (rectangles), so it's massively over kill, but it should provide the point...

(gif仅以7fps运行,而不是200fps)

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new VehiclesComponent(10000));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class VehiclesComponent extends JComponent implements ActionListener {

        private Vehicle[] vehicles;
        private Timer timer;

        public VehiclesComponent(int n) {
            vehicles = Vehicle.generateVehicle(n, getPreferredSize());
            timer = new Timer(5, this);

            timer.start();
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;

            for (int i = 0; i < vehicles.length; i++) {
                vehicles[i].draw(g2);
            }
        }

        @Override
        public void actionPerformed(ActionEvent e) {

            //check collision in here
//          for (Vehicle v : vehicles) {
//              if (Vehicle.intersectsOther(v, vehicles)) {
//                  v.collisionSideEffect();
//              }
//          }

        //move all in here
            for (Vehicle v : vehicles) {
                v.move(this.getSize());
            }

            repaint();
            //?? repaint slower than paintComponent
        }

    }

    public static class Vehicle {

        protected static final int SIZE = 5;
        protected static final Color[] COLORS = new Color[]{
            Color.BLACK,
            Color.BLUE,
            Color.CYAN,
            Color.DARK_GRAY,
            Color.GREEN,
            Color.MAGENTA,
            Color.ORANGE,
            Color.PINK,
            Color.RED,
            Color.WHITE,
            Color.YELLOW
        };

        private int x = 0;
        private int y = 0;

        private int xDelta;
        private int yDelta;

        private Shape car;
        private Color color;

        public static Vehicle[] generateVehicle(int count, Dimension bounds) {

            Vehicle[] vehicles = new Vehicle[count];
            for (int index = 0; index < vehicles.length; index++) {
                vehicles[index] = new Vehicle(bounds);
            }

            return vehicles;

        } 

        public Vehicle(Dimension size) {

            x = (int)(Math.random() * (size.width - SIZE));
            y = (int)(Math.random() * (size.height - SIZE));

            xDelta = (int)(Math.random() * 3) + 1;
            yDelta = (int)(Math.random() * 3) + 1;
            car = new Rectangle(SIZE, SIZE);

            color = COLORS[(int)(Math.random() * COLORS.length)];

        }

        public void move(Dimension size) {
            x += xDelta;
            y += yDelta;

            if (x < 0) {
                x = 0;
                xDelta *= -1;
            } else if (x + SIZE > size.width) {
                x = size.width - SIZE;
                xDelta *= -1;
            }
            if (y < 0) {
                y = 0;
                yDelta *= -1;
            } else if (y + SIZE > size.height) {
                y = size.height - SIZE;
                yDelta *= -1;
            }

        }

        public void draw(Graphics2D g2) {
            g2.translate(x, y);
            g2.setColor(color);
            g2.fill(car);
            g2.translate(-x, -y);
        }

    }

}

您还可以查看此示例向上以随机方向提取了4500张图像,并展示了一些优化技术.

You could also take a look at this example which renders upwards of 4500 images in random directions and demonstrates some optimisation techniques.

您还可以查看此示例能够同时对方向和旋转进行动画处理,最多可显示10,000张图像

You can also take a look at this example which is capable of animating both in direction and rotation, upwards of 10, 000 images

这篇关于repaint()的绘制速度比paintComponent()慢吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆