绘制一个不会在下一个油漆中消失的矩形 [英] Drawing a rectangle that won't disappear in next paint

查看:89
本文介绍了绘制一个不会在下一个油漆中消失的矩形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建一个绘制矩形的JPanel。专家组需要绘制大量的矩形,但它们不会移动。
我的问题的一个解决方案是创建一个包含我已创建的所有矩形的列表,并在每次调用Paint时绘制它们。但是有很多矩形,它会减慢计算机的速度。

我也尝试使用repaint(x,y,height,width)来rapaint只是新矩形的空间,但它不起作用。 (JPanel不断删除以前的矩形。)
在排序中,我需要绘制不会消除每个绘画的矩形。或者不会抹去以前绘画的绘画方法,或不会绘制背景。
这是我的JPanel类的一部分:

  class MyPanel extends JPanel {
private int x,y ,大小;
私有颜色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);
}

}

解决方案


  1. 不要覆盖 paint WITHOUT VERY,非常好的理由... use paintComponent 改为

  2. 总是调用 super.paintXxx ,这些方法在后台执行很多操作,失败调用super只会回来并困扰你。

  3. 如果你使用多个窗格作为矩形,使 MyPanel 透明。

Paint是无状态的。最后一个油漆与下一个油漆没有任何关系。在每个绘画请求中,您都希望更新整个状态。



Andrew提出的双缓冲(或缓冲缓冲)是非常好的,我强烈建议您在这段时间,我把这个小例子放在一起......





基本上,按住鼠标按钮,它会每隔40毫秒(大约每秒25帧)向面板中随机添加一个矩形。



我得到了1000个矩形没有任何问题,无法调整窗口的大小,并发出或明显放缓...

  public class MyPanel extends JPanel { 

私人列表< MyRectangle> lstShapes;
私人定时器填充;

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 +宽度> getWidth()){
x = getWidth() - 宽度;
}
if(y + height> getHeight()){
y = getHeight() - height ;


颜色color = new Color(
(int)(Math.random()* 255),
(int)(Math.random() * 255),
(int)(Math.random()* 255));

lstShapes.add(new MyRectangle(x,y,wid高度,颜色));
repaint();
}
});
populate.setInitialDelay(0);
populate.setRepeats(true);
populate.setCoalesce(true);
$ b addMouseListener(new MouseAdapter(){
@Override
public void mousePressed(MouseEvent e){
populate.restart();
}

@Override
public void mouseReleased(MouseEvent e){
populate.stop();
}
});


$ b @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;
$ b 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);




$ / code>

有一个去吧,很有趣;)

ps-在我注意到速度减慢之前,我得到了超过5000个矩形(我将代码修改为10毫秒的延迟,每个勾号增加了10个新的矩形)

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);
    }

}

解决方案

  1. Don't override paint WITHOUT VERY, VERY good reason...use paintComponent instead
  2. 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.
  3. If you're using multiple panes as rectangles, make the MyPanel transparent.

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'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...

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).

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);

        }
    }
}

have a go, it's fun ;)

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)

这篇关于绘制一个不会在下一个油漆中消失的矩形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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