Java Swing:drawLine非常慢

时间:2012-10-24 06:17:55

标签: java swing graphics fullscreen doublebuffered

我正在使用swing编写一个java应用程序,我需要在正方形上方绘制一个网格。为此,我使用drawLine(...)类提供的Graphics方法。

除了绘制每一条线需要花费大量时间(50条线超过20秒......)之外,一切正常。我甚至可以看到实时绘制的线条。奇怪的是,水平线的绘制速度比垂直线快(几乎是瞬间)。

我可能做错了什么。这是网格的代码。

public void drawGrid(Graphics g){
    g.setColor(new Color(255, 255, 255, 20));
    int width = getWidth();
    int height = (int) (width * Utils.PLATE_RATIO);
    int step = pixelSize*gridSpacing;
    Color bright = new Color(255, 255, 255, 100);
    Color transparent = new Color(255, 255, 255, 20);
    for(int ix = insets.left + step;                        
            ix < width; ix += step){
        if(((ix - insets.left) / step) % 10 == 0){
            g.setColor(bright);
        }
        else{
            g.setColor(transparent);
        }
        g.drawLine(ix, insets.top, ix, height+insets.top);
    }
    for(int iy = insets.top+step;
            iy < (insets.top + height); iy += step){
        if(((iy - insets.top) / step) % 10 == 0){
            g.setColor(bright);
        }
        else{
            g.setColor(transparent);
        }
        g.drawLine(insets.left, iy, width + insets.left, iy);
    }
}

2 个答案:

答案 0 :(得分:4)

您发布的代码很好,没有任何问题。
下面是使用您的方法的组件的一个工作示例(稍微简化):

public static class MyGrid extends JComponent
{
    private int step = 10;

    public MyGrid ()
    {
        super ();
    }

    public Dimension getPreferredSize ()
    {
        return new Dimension ( 500, 500 );
    }

    protected void paintComponent ( Graphics g )
    {
        super.paintComponent ( g );
        drawGrid ( g );
    }

    public void drawGrid ( Graphics g )
    {
        int width = getWidth ();
        int height = getHeight ();
        Color bright = new Color ( 255, 255, 255, 200 );
        Color transparent = new Color ( 255, 255, 255, 100 );

        for ( int ix = step; ix < width; ix += step )
        {
            if ( ( ix / step ) % 10 == 0 )
            {
                g.setColor ( bright );
            }
            else
            {
                g.setColor ( transparent );
            }
            g.drawLine ( ix, 0, ix, height );
        }

        for ( int iy = step; iy < height; iy += step )
        {
            if ( ( iy / step ) % 10 == 0 )
            {
                g.setColor ( bright );
            }
            else
            {
                g.setColor ( transparent );
            }
            g.drawLine ( 0, iy, width, iy );
        }
    }
}

我猜这段代码之外还有一些问题。

P.S。有点偏离但是...

我建议你计算绘画区域的可见部分(使用JComponent的getVisibleRect ()方法或图形g.getClip ().getBounds ()方法)并限制你的绘画只用那个区域。

如果组件的绘制非常大(例如,组件面积为10000x10000像素),那么小优化可以加速组件的绘制。

答案 1 :(得分:-1)

根据@sureshKumar的建议,以下是我使用Double-Buffering解决问题的方法。我只是在绘制一个屏幕外图像,并在绘图结束时简单地调用drawImage()。这似乎可以解决问题。

编辑:只有当您想要从drawGrid()方法之外调用您的绘画方法(在我的情况下为paintComponent(...))时,这似乎才有用。

以下是代码:

private Graphics bufferGraphics;
private Image offScreen;
private Dimension dim;
//other attributes not shown...

public CentralPanel(){
    //Some initialization... (not shown)

    //I added this listener so that the size of my rectangle
    //and of my grid changes with the frame size
    this.addComponentListener(new ComponentListener() {

        @Override
        public void componentResized(ComponentEvent e) {
            dim = getVisibleRect().getSize();
            offScreen = createImage(dim.width, dim.height);
            bufferGraphics = offScreen.getGraphics();
            repaint();
            revalidate();
        }
        //other methods of ComponentListener not shown
    });
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.drawImage(offScreen, 0, 0, null);
}

public void drawGrid(){
    int width = dim.width - insets.left - insets.right;
    width -= (width % plateSize.getXSize());
    int height = (int) (width*Utils.PLATE_RATIO);
    height -= (height % plateSize.getYSize());
    int step = pixelSize*gridSpacing;
    Color bright = new Color(255, 255, 255, 100);
    Color transparent = new Color(255, 255, 255, 20);
    for(int ix = insets.left + step;                        
            ix < (width+insets.left); ix += step){
        if(((ix - insets.left) / step) % 10 == 0){
            bufferGraphics.setColor(bright);
        }
        else{
            bufferGraphics.setColor(transparent);
        }
        //I am now drawing on bufferGraphics instead 
        //of the component Graphics
        bufferGraphics.drawLine(ix, insets.top, ix, height+insets.top);
    }
    step *= Utils.PLATE_RATIO;
    for(int iy = insets.top+step;
            iy < (insets.top + height); iy += step){
        if(((iy - insets.top) / step) % 10 == 0){
            bufferGraphics.setColor(bright);
        }
        else{
            bufferGraphics.setColor(transparent);
        }
        bufferGraphics.drawLine(insets.left, iy, width + insets.left, iy);
    }
}

P.S。:如果这应该作为我的问题的编辑添加,请告诉我,我会这样做。