2015-06-05 181 views
3

我正在尝试用Java Swing绘制线条。目标是在面板内打开图像并在该图像上绘制线条。当我尝试画一个线并拖动鼠标,我得到这个行为:用Java swing绘制一条线绘制多条线

enter image description here

我的代码:

// Somewhere in the code: 
imgLabel= new JLabel(new ImageIcon(buffImage)); // buffImage is a BufferedImage 

... 
Point point1; 
Point point2; 
Line2D line2d; 

public void draw() { 
    Graphics2D g1 = this.buffImage.createGraphics(); 
    g1.setRenderingHint(enderingHints.KEY_ANTIALIASING, 
      RenderingHints.VALUE_ANTIALIAS_ON); 
    g1.setColor(Color.RED); 
    g1.setStroke(new BasicStroke(1.5f)); 
    if (point1 != null && point2 != null) { 
     g1.draw(line2d); 
     this.imgLabel.repaint(); 
    } 
} 

class ImageMouseListener extends MouseAdapter { 
    @Override 
    public void mousePressed(MouseEvent me) { 
     point1 = me.getPoint(); 
    } 

    @Override 
    public void mouseDragged(MouseEvent me) { 
     point2 = me.getPoint(); 
     line2d = new Line2D.Double(point1, point2); 
     draw(); 
    } 
} 
+0

寻找mouseDragged尝试将其更改为mouseReleased – JajaDrinker

+0

我仍然需要使用mouseDragged方法才能在绘制它时看到该行。 – Med

+0

我真的不明白你真正想要的东西吗?你想看到被拖动的线,只画出最后一行是吗? – JajaDrinker

回答

4

您提供图纸的代码是正确的。问题在于,无论何时移动鼠标光标,程序都会从​​起点到当前鼠标位置绘制另一条线,从而产生您向我们展示的效果(您只是忘记删除旧线)。

为了解决这个问题,每次移动鼠标时,你需要:

  1. 绘制再次使用XOR mode
  2. 绘制第二线前行。

这意味着您需要存储以前的鼠标位置,以便调用mouseDragged()

我使用JOGL而不是Graphics,使用setXORMode(Color color)实现了非常类似的东西。这也适用于Graphics类。您可以阅读图形类herehere中的异或模式。
我不知道你要把多少复杂性放在你的项目上,但是如果你期望更复杂的话,我会建议使用像JOGL这样的库。这非常有用。


UPDATE:寻址重叠线

这是一个更具挑战性的任务。首先,如果你很好奇并想完全理解重叠线条为什么会产生如此有趣的效果,我建议你阅读this

我想唯一的办法就是存储每一行​​的坐标和每一个新的线描

这是一个很好的第一种方法后重绘他们。保持一个数据结构,所有的顶点和它们相关联的形状将允许你继续调用repaint()。您还必须意识到,这样做时,相交点不会在屏幕上突出显示(您会看到一种颜色或另一种颜色),但这应该已经是您的意图。

你知道bounding box是什么?你可以为任何线(或形状)创建一个边界框,它只是一个围绕你的点的矩形。

让我们假设你确实为每一行保留了一个边界框。当添加一个新行,你可以:

  1. 检查,如果你要绘制拦截任何边界框
  2. 如果是这样,重新绘制这些边框相关联的所有线的线条
  3. 添加新没有异或模式的线

这种技术比重画整个屏幕更好,因为可能存在任意数量的行,并且您可以编写一个体面高效的算法来检查边界框的交点。

请注意,截取边界框并不意味着存在重叠,因为存在一些例外(例如平行线),这使得这是错误的假设。同时请记住,避免看到由于异或模式而使用不同颜色绘制的线交点的唯一方法是在没有XOR模式的情况下绘制它们。您必须非常小心地在正确的时间打开和关闭XOR模式。

我发现了一个有趣的页面,提供了解决此问题的其他方法,您可以查看它here

+1

不错的答案,再加上留给做研究的空间..不只是简单的源代码提供:) –

+0

我认为使用XOR模式再次绘制上一行将实际删除该行?将尽快检查。 – Med

+0

@Med - 是的,你是对的。我相信我提供的链接应该足以理解它是如何工作的。尽管如此,大部分计算机图形学书籍都涵盖了这个主题 – goncalotomas

0

您的问题是代码

public void mouseDragged(MouseEvent me) { 
    point2 = me.getPoint(); 
    line2d = new Line2D.Double(point1, point2); 
    draw(); 

具体的Line2D =新Line2D.Double(点1,点2)的这部分; 它正在绘制一条拖动鼠标的新线。