问题描述
我正在绘画使用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
}
}
推荐答案
首先查看在AWT和Swing中绘画.请记住,repaint
只是对RepaintManager
的建议,RepaintManager
可以选择将多个repaint
调用合并为较少的实际绘画事件.
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 Vehicle
s (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()慢吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!