3

我正在使用 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);
    }
}
4

2 回答 2

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

我想那段代码之外有一些问题。

PS有点题外话,但是...

我建议您计算绘画区域的可见部分(使用 JComponent 的getVisibleRect ()方法或 Graphicsg.getClip ().getBounds ()方法)并将您的绘画限制在该区域。

如果组件真的很大(例如组件的区域为 10000x10000 像素),那么这个小的优化可以加速组件的绘制。

于 2012-10-24T09:32:49.093 回答
-1

这是我使用双缓冲解决问题的方法,正如@sureshKumar 所建议的那样。我只是在屏幕外的图像上绘图,并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);
    }
}

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

于 2012-10-25T01:33:15.350 回答