Java:Graphics 2d,绘制速度不够快

时间:2014-02-27 06:23:02

标签: java awt graphics2d

我正在寻找一个相当简单的(简单来说,我的意思是没有什么需要太多的代码行)来解决以下问题:

我有一个绘画应用程序。该应用的代码位于:https://github.com/Tigatok/JavaProjects/tree/master/Paint2.0

这是我的问题:

如何使方线与pencilLine一样平滑?

2 个答案:

答案 0 :(得分:4)

对于细线,您当前正在调用

g2D.drawLine(oldX, oldY, currentX, currentY);

对于粗线,您只需要调用

g2D.fillRect(currentX, currentY, getXSize(), getYSize());

这意味着当您快速移动鼠标时,前一个鼠标位置和新鼠标位置之间将没有任何关联。

一个简单的解决方案已经允许实现接近你可能想要的效果,可以将第二个调用更改为

g2D.setStroke(new BasicStroke(getXSize()));
g2D.drawLine(oldX, oldY, currentX, currentY);

但是,您当前的绘画代码有几种可能的改进。您应该考虑根据一组布尔标志做出关于如何绘制的决定。相反,您可以考虑类似Pen接口,允许您通过使用此接口的不同实现在不同的笔之间切换。

已经提到过,您可以将点组装成Path2D并绘制此路径。这是一个很好的建议,你也应该考虑一下:它提供了一些很好的可能性。例如,您可以定义Stroke并使用任意笔形状创建“描边形状”。

然而,所有这些变化可能需要相当多的重构,因此,直到现在,它们只是相当模糊的建议。


编辑:添加了基于评论的示例

我可以想象你想要达到的效果。但这可能相当困难。一个简单的解决方案,至少可以关闭到你想要的东西可能是这个(使用来自http://www.jhlabs.com/java/java2d/strokes/的类的简化版本)

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.FlatteningPathIterator;
import java.awt.geom.GeneralPath;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Rectangle2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class SharpiePaintTest
{
    public static void main(String[] args) 
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createAndShowGUI();
            }
        });
    }    

    private static void createAndShowGUI()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(new SharpiePaintTestPanel());
        f.setSize(1100,600);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class SharpiePaintTestPanel extends JPanel
{
    @Override
    protected void paintComponent(Graphics gr)
    {
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D)gr;
        g.setColor(Color.BLACK);

        Path2D path = new Path2D.Double();
        path.moveTo(300,300);
        path.curveTo(400, 400, 400, 300, 300, 200);

        g.setStroke(new ShapeStroke(new Rectangle2D.Double(0,0,3,15), 3.0f));
        g.draw(path);
    }
}

// Based on http://www.jhlabs.com/java/java2d/strokes/ShapeStroke.java,
// only slightly simplified
class ShapeStroke implements Stroke {
    private Shape shape;
    private float advance;
    private static final float FLATNESS = 1;

    public ShapeStroke(Shape shape, float advance ) {
        this.advance = advance;
        Rectangle2D bounds = shape.getBounds2D();
        this.shape = AffineTransform.getTranslateInstance(
            -bounds.getCenterX(), -bounds.getCenterY()).createTransformedShape(shape);
    }

    @Override
    public Shape createStrokedShape( Shape shape ) {
        GeneralPath result = new GeneralPath();
        PathIterator it = new FlatteningPathIterator( shape.getPathIterator( null ), FLATNESS );
        float points[] = new float[6];
        float moveX = 0, moveY = 0;
        float lastX = 0, lastY = 0;
        float thisX = 0, thisY = 0;
        int type = 0;
        float next = 0;
        while (!it.isDone() ) {
            type = it.currentSegment( points );
            switch( type ){
            case PathIterator.SEG_MOVETO:
                moveX = lastX = points[0];
                moveY = lastY = points[1];
                result.moveTo( moveX, moveY );
                next = 0;
                break;

            case PathIterator.SEG_CLOSE:
                points[0] = moveX;
                points[1] = moveY;
                // Fall into....

            case PathIterator.SEG_LINETO:
                thisX = points[0];
                thisY = points[1];
                float dx = thisX-lastX;
                float dy = thisY-lastY;
                float distance = (float)Math.sqrt( dx*dx + dy*dy );
                if ( distance >= next ) {
                    float r = 1.0f/distance;
                    while (distance >= next ) {
                        float x = lastX + next*dx*r;
                        float y = lastY + next*dy*r;
                        AffineTransform t = new AffineTransform();
                        t.setToTranslation( x, y );
                        result.append( t.createTransformedShape(this.shape), false );
                        next += advance;
                    }
                }
                next -= distance;
                lastX = thisX;
                lastY = thisY;
                break;
            }
            it.next();
        }

        return result;
    }

}

答案 1 :(得分:1)

与Java2D相比,Java2D的绘制速度还不够快,尽管与渲染库的速度相比,Java2D是一个缓慢的库。

无论如何,在您的计划和Path2D.Double中声明Path2D.FloatmouseDrag,将mouseEvent的坐标添加到此Path2D对象。
如果是您要添加的第一个坐标,请使用moveTo()方法,或使用lineTo()方法。
完成后,请致电repaint()

在重新绘制中,绘制Path2D,如下所示:

public void paintComponent(Graphics graphics)
{
  Graphics2D g = (Graphics2D) graphics;
  // set appropriate color and line thickness here.
  g.draw(path);
  // draw other stuff.
  g.dispose();
}