绘制一个在下一次绘制中不会消失的矩形
我试图创建一个绘制矩形的 JPanel.面板需要绘制很多矩形,但它们不会移动.我的问题的一个解决方案是创建一个包含我已经创建的所有矩形的列表,并在每次Paint"调用中绘制它们.但是有很多矩形会减慢计算机的速度.
我还尝试使用 repaint(x, y, height, width) 来绘制新矩形的空间,但它不起作用.(JPanel 不断擦除之前的矩形.)在排序中,我需要绘制不会在每次绘制时消失的矩形.或者一种不会擦除以前绘制或不会绘制背景的绘画方法.那是我的 JPanel 类的一部分:
I trying to create a JPanel that draws rectangles. The Panel needs to draw alot of rectangles, but they dont move.
One solution to my problem was to create an list with all the rectangles i already created and draw they all in every call of "Paint". But there is a lot of rectangles and it slows the computer.
I also tried to use repaint(x, y, height, width) to rapaint just the space of the new rectangle but it did not work. (JPanel keeps erasing previous rectangles.)
In sort, i need to draw rectangles that wont disappear every paint. Or a paint method that wont erase previous draws, or wont paint the background.
That is part of my JPanel class:
class MyPanel extends JPanel{
private int x, y, size;
private Color c;
public void DrawRect(int x, int y, int size, Color c){
this.x = x;
this.y = y;
this.size = size;
this.c = c;
repaint();
}
@Override
public void
paint(Graphics g) {
g.setColor(c);
g.fillRect(x, y, size, size);
}
}
- 不要在没有非常非常好的理由的情况下覆盖
paint
...使用paintComponent
代替 - 总是调用
super.paintXxx
,这些方法在后台做了很多事情,不调用super只会回来困扰你. - 如果您将多个窗格用作矩形,请将
MyPanel
设为透明.
- Don't override
paint
WITHOUT VERY, VERY good reason...usepaintComponent
instead - Always call
super.paintXxx
, these methods do a lot in the background, failing to call super is only going to come back and haunt you. - If you're using multiple panes as rectangles, make the
MyPanel
transparent.
Paint 是无状态的.上一个油漆和下一个油漆之间没有联系.对于每个绘制请求,您都需要更新整个状态.
Paint's are stateless. There is no connection between the last paint and the next. On each paint request you are expected to update the entire state.
Andrew 提出的双缓冲(或后缓冲)建议非常好,我强烈建议您查看并实施它.
Andrew's suggest of double buffering (or back buffering) is and excellent one, and I highly encourage you to have a look an implementing it.
同时,我把这个小例子放在一起......
In the mean time, I put this little example together...
基本上,您按住鼠标按钮,它会每 40 毫秒(大约每秒 25 帧)随机向面板添加另一个矩形.
Basically, you press and hold the mouse button and it will randomly add another rectangle to the panel every 40 milli-seconds (roughly 25 frames a second).
我把它提高到 1000 rects 没有任何问题,能够在没有问题的情况下调整窗口大小或明显减慢...
I got this up to a 1000 rects without any issue, was able to resize the window without and issue or obviously slow down...
public class MyPanel extends JPanel {
private List<MyRectangle> lstShapes;
private Timer populate;
public MyPanel() {
lstShapes = new ArrayList<MyRectangle>(25);
populate = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int x = (int) (Math.random() * getWidth());
int y = (int) (Math.random() * getHeight());
int width = (int) (Math.random() * (getWidth() / 4));
int height = (int) (Math.random() * (getHeight() / 4));
if (x + width > getWidth()) {
x = getWidth() - width;
}
if (y + height > getHeight()) {
y = getHeight() - height;
}
Color color = new Color(
(int) (Math.random() * 255),
(int) (Math.random() * 255),
(int) (Math.random() * 255));
lstShapes.add(new MyRectangle(x, y, width, height, color));
repaint();
}
});
populate.setInitialDelay(0);
populate.setRepeats(true);
populate.setCoalesce(true);
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
populate.restart();
}
@Override
public void mouseReleased(MouseEvent e) {
populate.stop();
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (MyRectangle rect : lstShapes) {
rect.paint(g2d);
}
FontMetrics fm = g2d.getFontMetrics();
String text = Integer.toString(lstShapes.size());
g2d.setColor(getForeground());
g2d.drawString(text, getWidth() - fm.stringWidth(text), getHeight() - fm.getHeight() + fm.getAscent());
}
public class MyRectangle extends Rectangle {
private Color color;
public MyRectangle(int x, int y, int width, int height, Color color) {
super(x, y, width, height);
this.color = color;
}
public Color getColor() {
return color;
}
public void paint(Graphics2D g2d) {
g2d.setColor(getColor());
g2d.fill(this);
}
}
}
试一试,很有趣;)
ps- 在我注意到速度变慢之前,我已经达到了超过 5000 个矩形(我将代码修改为 10 毫秒的延迟,并且每个刻度添加了 10 个新矩形)
ps- I got to up to over 5000 rectangles before I noticed a slow down (I modified the code down to a 10 milli second delay and was adding 10 new rectangles per tick)