Начните с обзора Painting in AWT and Swing. Помните, repaint
- это только предложение, сделанное для RepaintManager
, RepaintManager
может выбрать объединение нескольких repaint
звонков в меньшее количество актуальных событий.
Удостоверяются, что вы звоните super.paintComponent
, иначе вы в конце концов не закончите странные артефакты.
Не допускайте, прямо или косвенно, изменения состояния компонента или других компонентов из любого метода краски, это приведет к созданию нового запроса repaint
, что может привести к циклу событий красок, которые могли бы потребляйте ваши циклы процессора. Это означает, что не звоните timer.start()
!
Без плавного примера, который я прошел, я соскочил вместе. Теперь это оживляющий 10 000 индивидуальных Vehicle
S (прямоугольники), так что это массово над убить, но она должна обеспечивать точку ...
(МФП работает только на 7 кадров в секунду, а не ваш 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);
}
}
}
Вы также мог бы взглянуть на this example, которая делает вверх 4500 изображений в произвольных направлениях и демонстрируют некоторые методы оптимизации.
Вы также можете посмотреть на this example, который способен анимировать как в направлении вращения и, свыше 10 000 изображений
'общественного недействительными paintComponent (Graphics г) {..' как уже упоминалось здесь ** на ежедневной основе **, который должен быть «public void paintComponent (Graphics g) {super.paintComponent (g); ..' И 1) move '// может позже измениться timer.start();' вне метода, который мы не контролируем, когда и сколько раз он вызывается. 2) Используйте логическую и согласованную форму отступающих кодовых строк и блоков. Отступы предназначены для того, чтобы поток кода стал проще следовать! –
И он должен оставаться 'protected' – MadProgrammer
Начнем с [Живопись в AWT и Swing] (http://www.oracle.com/technetwork/java/painting-140037.html)'. 'repaint' делает запрос к' RepaintManager', который отвечает за планирование событий рисования в очереди событий. Чтобы повысить производительность, запрос 'repaint' может быть объединен в одно (или меньшее количество) событий рисования. – MadProgrammer