简体   繁体   English

使用Java swing绘制一条线会绘制多条线

[英]Drawing a line with Java swing draws multiple lines

I'm trying to draw lines with Java Swing. 我正在尝试使用Java Swing绘制线条。 The goal is to open an image inside the panel and draw lines on that image. 目标是在面板内打开图像并在该图像上绘制线条。 When I try to draw a single line and drag the mouse, I get this behavior: 当我尝试绘制单行并拖动鼠标时,我得到以下行为:

在此输入图像描述

My code: 我的代码:

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

The code you provide for drawing is correct. 您为绘图提供的代码是正确的。 The issue here is that whenever you move your mouse cursor, the program is going to draw another line from the starting point to your current mouse position, resulting in the effect you show us (you're just forgetting to delete the old line). 这里的问题是,无论何时移动鼠标光标,程序都会从​​起点到当前鼠标位置绘制另一条线,从而产生您向我们展示的效果(您只是忘记删除旧线)。

To fix this, every time the mouse is moved you need to: 要解决此问题,每次移动鼠标时,您需要:

  1. Draw the previous line again using XOR mode 使用XOR模式再次绘制上一行
  2. Draw the second line. 画出第二行。

This means you need to store the previous mouse position for when mouseDragged() is called. 这意味着您需要在mouseDragged()时存储上一个鼠标位置。

I implemented something very similar using JOGL instead of Graphics , using setXORMode(Color color) . 我使用setXORMode(Color color)使用JOGL而不是Graphics实现了非常类似的东西。 This is also available for the Graphics class. 这也适用于Graphics类。 You can read about the XOR mode in the Graphics class here and here . 您可以在此处此处阅读Graphics类中的XOR模式。
I don't know how much complexity you're going to put on your project, but if you're anticipating more complexity I would advise using a library like JOGL. 我不知道你要对你的项目有多大的复杂性,但是如果你预计会有更多的复杂性,我会建议使用像JOGL这样的库。 It's VERY useful. 这非常有用。


UPDATE: Addressing overlapped lines 更新:寻址重叠的行

This is a more challenging task. 这是一项更具挑战性的任务。 First, if you're curious and want to fully understand why overlapped lines produce such an intriguing effect, I would advise you to read this . 首先,如果你很好奇并希望完全理解为什么重叠的线会产生这种有趣的效果,我建议你阅读这个

I guess the only way is to store every line coordinates and redraw them after each new line drawing 我想唯一的方法是存储每个线坐标并在每个新线绘制后重绘它们

This is a very good first approach. 这是一个非常好的第一种方法。 Keeping a data structure will all vertices and the shapes they are associated with would allow you to keep calling repaint() . 保持数据结构将所有顶点和它们关联的形状允许您继续调用repaint() You must also be aware that in doing so the intersect points will not stand out in your screen (you'll see either one line color or the other, no intermediate colors), but this should already be your intent. 你还必须意识到这样做,交叉点不会在你的屏幕中突出(你会看到一种颜色或另一种颜色,没有中间颜色),但这应该是你的意图。

Do you know what a bounding box is? 你知道边界框是什么吗? You can create a bounding box for any line (or shape) which is just a rectangle that surrounds your points. 您可以为任何线条(或形状)创建边界框,该边框只是围绕您的点的矩形。

Let's assume you do in fact keep a bounding box for each line. 假设你确实为每一行保留了一个边界框。 When adding a new line, you could: 添加新行时,您可以:

  1. Check if the line you're about to draw intercepts any bounding boxes 检查您要绘制的线是否截取任何边界框
  2. If it does, repaint all lines associated with those bounding boxes 如果是,则重新绘制与这些边界框关联的所有行
  3. Add the new line without XOR mode 在没有XOR模式的情况下添加新行

This technique is better than redrawing the entire screen because there could be an arbitrary number of lines already present, and you can write a decently efficient algorithm to check for bounding box intersections. 这种技术比重绘整个屏幕更好,因为可能存在任意数量的行,并且您可以编写一个相当有效的算法来检查边界框交叉点。

Note that intercepting a bounding box does not imply that there is overlapping, because there are some exceptions (eg parallel lines) that make this a wrong assumption. 请注意,拦截边界框并不意味着存在重叠,因为有一些例外(例如,平行线)使得这是一个错误的假设。 Also keep in mind that the only way to avoid seeing line intersections painted with a distinct color due to XOR mode is to draw them without XOR mode. 另外请记住,避免看到由于XOR模式而使用不同颜色绘制的线条交叉点的唯一方法是在没有XOR模式的情况下绘制它们。 You will have to be very careful toggling XOR mode on and off at the right times. 您必须非常小心地在正确的时间打开和关闭XOR模式。

I found an interesting page about additional ways you could tackle this problem, you can check it here . 我找到了一个有趣的页面,介绍了解决这个问题的其他方法,你可以在这里查看

your problem is this part of your code 你的问题是代码的这一部分

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

specifically line2d = new Line2D.Double(point1, point2); 特别是line2d = new Line2D.Double(point1,point2); it's drawing a new line one the mouse is dragged. 它正在绘制一条拖动鼠标的新线。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM