【问题标题】:Multiple lines are gets drawn with Graphics2D使用 Graphics2D 绘制多条线
【发布时间】:2016-06-10 09:14:52
【问题描述】:

我正在尝试开发一个将几何图形绘制到图像上并保存它们的小型应用程序。我的面板类中有这段代码:

@Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        if (getBufferedImage() != null)
        {
            g.drawImage(getBufferedImage(), 120, 0, getBufferedImage().getWidth(), getBufferedImage().getHeight(), null);
        }

        for (Shape s : getShapes())
        {
            if (getBufferedImage() != null)
            {
                Graphics2D graphics = getBufferedImage().createGraphics();
                s.draw(graphics);
            }
        }

    }

getBufferedImage() 将返回加载图像的缓冲图像。而s.draw() 是我定义的各个形状类中的方法。

就像在 Rectangle 中一样,它有代码:graphics.drawRect()
线路:graphics.drawLine()

Line 类中的方法:

@Override
public void draw(Graphics g)
{
    g.setColor(getColor());

    g.drawLine(getXAxis(), getYAxis(), getWidth() + getXAxis(), getHeight() + getYAxis());
}

这些是我重写的 MouseAdapter 方法

@Override
public void mousePressed(MouseEvent event)
{
    switch (getSelectedShape())
    {
        case Rectangle:
        {
            getShapes().add(new Rectangle(event.getX(), event.getY(), getSelectedColor(), isFilled()));
            break;
        }

        case Line:
        {
            getShapes().add(new Line(event.getX(), event.getY(), getSelectedColor()));
            break;
        }
    }

    repaint();
}

@Override
public void mouseDragged(MouseEvent event)
{
    if (event == null || event.getPoint() == null || getShapes().size() <= 0)
    {
        return;
    }

    Shape currentShape = getShapes().get(getShapes().size() - 1);

    if (currentShape == null)
    {
        return;
    }

    currentShape.mouseDragged(event.getPoint());

    repaint();
}

现在,当我绘制任何形状时,会改为绘制多个形状:

【问题讨论】:

  • 你能告诉我们s.draw(g);上有什么代码吗?我希望你在做一些基于 MouseListener、MouseMotionEvent 的计算。
  • 为什么要在循环中画两次 s.draw(graphics);和 s.draw(g);
  • @shazin 我已经编辑了我的问题
  • @Beniton 我通过提供 Line 类的 draw() 方法编辑了问题
  • @SaikiranGosikonda 能否也包含 MouseListener 相关代码。以及如何计算坐标、高度和宽度?

标签: java swing graphics draw


【解决方案1】:

给你。

我有一些变量

private boolean start = false;
private ArrayList<Line> shapes = new ArrayList<Line>();
private Line currentLine = null;

添加鼠标处理程序

MouseHandler mouseHandler = new MouseHandler();
addMouseListener(mouseHandler);
addMouseMotionListener(mouseHandler);

MouseHandler 部分。

private class MouseHandler extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent e) {
            if (e.getButton() == MouseEvent.BUTTON1) {
                start = true;
                currentLine = new Line();
                currentLine.setFirst(new Point(e.getX(), e.getY()));
                currentLine.setLast(new Point(e.getX(), e.getY()));
                shapes.add(currentLine);
            }
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            if (e.getButton() == MouseEvent.BUTTON1) {
                start = false;
                currentLine.setLast(new Point(e.getX(), e.getY()));
                currentLine = null;
                repaint();
            }
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            if (start) {
                currentLine.setLast(new Point(e.getX(), e.getY()));
                repaint();
            }
        }
    }

还有颜料

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.setColor(Color.black);
    for(Line line : shapes){
        g.drawLine(line.getFirst().x, line.getFirst().y, line.getLast().x, line.getLast().y);
    }
}

用于将其保存到 BufferedImage。

public void saveImage() throws IOException {
   BufferedImage image = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_ARGB);
   Graphics2D graphics = image.createGraphics();
   graphics.setColor(Color.black);
   for (Line line : shapes) {
            graphics.drawLine(line.getFirst().x, line.getFirst().y, line.getLast().x, line.getLast().y);
   }
   graphics.dispose();
        ImageIO.write(image, "png", new File("Beniton drawing.png"));

}

添加一个按钮并调用 saveImage()

【讨论】:

  • 但是,这段代码也不起作用。如果我没有任何图像并且我在空面板上绘制形状,我在问题中给出的代码工作正常。仅当我尝试在 BufferedImage 上绘制形状时才会导致问题
  • 上面的代码运行良好。您只需要根据您的要求细化您的代码。基础是一样的。
  • 如果您尝试在缓冲图像上绘制形状,它是否有效。你能告诉我你是如何在图像上绘制形状的吗
  • 我没有尝试在缓冲图像上绘图。但我相信它会起作用。它只是获取图形并进行绘图。所以它应该可以工作。
  • Graphics2D 图形 = getBufferedImage().createGraphics(); shape.draw(图形);在形状类中,我的代码与您在答案中给出的代码相同
【解决方案2】:

从绘制代码中拆分 BufferedImage 的创建。

@Override
public void paintComponent(Graphics g)
{
    Graphics2D graphics = (Graphics2D) g;
    for (Shape s : getShapes()) {
        graphics.draw(shape);
    }
}

public void saveAsImage()
{
    if (bufferedImage == null) {
        // Create bufferedImage
    }

    Graphics2D graphics = nufferedImage.createGraphics();
    paint(graphics);           
    graphics.dispose();
}

当然你也可以在paintComponent中只绘制bufferedImage,并在添加一个形状时创建一个新的bufferedImage,虽然这看起来效率低下,容易出错(当布局到其他尺寸时)。

除了需要的Graphics.dispose,代码不遵守“快速绘制没有副作用。”

【讨论】:

  • 但是,我应该在哪里调用这个 saveAsImage() 方法。如果我在 paintComponent() 方法中调用它,它会给出 stockOverflowError
  • 你在哪里需要缓冲图像?如果形状列表足够,您可以将其省略。如果缓冲图像用于平滑绘制,JPanel 默认使用“双缓冲”——交换两个缓冲区。所以也不需要缓冲图像。
  • Beniton 给出了我认为更合适的答案。
猜你喜欢
  • 1970-01-01
  • 2021-11-24
  • 1970-01-01
  • 2017-06-13
  • 2021-06-06
  • 2019-12-01
  • 2021-04-17
  • 2018-12-17
相关资源
最近更新 更多