1

我有一个充满大量圆圈(Ellipse2D)的面板。圆圈存储在二维数组(行和列)中。

我的目标是当我将鼠标拖到圆圈上时能够“绘制”圆圈。我最终会想要使用选择形状来改变选择形状中包含的所有圆圈的颜色。

我正在使用鼠标拖动侦听器,它不断扫描整个二维数组并检查当前点是否在圆圈内。像这样:

        addMouseMotionListener(new MouseAdapter() {

        public void mouseDragged(MouseEvent e) {

            currentColor = ColorSliderPanel.getRGB();

            for (int x = 0; x < numColumns; x++) {
                for (int y = 0; y < numRows; y++) {
                    if (circle[x][y].contains(e.getX(), e.getY())) {

                        circle[x][y].setColor(currentColor);
                        repaint();
                    }
                }
            }

        }
    });

上面的代码有效,但它真的很慢(1000+ 圈),因为它正在检查每一个对象。

肯定有更好的办法。我读过一些关于四叉树的文章,但我不确定四叉树是否比我需要的马力更大。

谢谢

我根据以下一些评论进行了以下更改。Circles 现在是一个线性 ArrayList。draw 方法只是简单地填充圆圈。进行此更改将速度提高了两个数量级。现在效果好多了。虽然,我仍然可以以适中的速度扫过面板并错过几圈。所以我可能需要进一步优化。

  Graphics2D g2d = (Graphics2D) getGraphics();

            for (Circle2D c : circles) {
                if (c.contains(p)) {
                    c.setColor(currentColor);
                   //Graphics2D g2d = (Graphics2D) getGraphics(); (moved)
                    c.draw(g2d);
                }
            }
4

4 回答 4

3

我个人这样做的方式是这样的:

  • 制作圆的线性数组(或链表,您可以选择)。
  • 在您的事件侦听器中,您在数组上线性迭代,针对您的鼠标位置点击测试每个圆圈,如果测试通过,您更改颜色
  • 这是最大的优化:由于我们正在讨论以相当高的频率(每次鼠标移动)进行绘制,因此您想确定必须重绘哪些圆圈。当您在上面的数组上进行迭代时,保持对必须更改的最大边界框的运行计数(一个围绕必须重绘的每个圆圈的矩形)
  • 现在您删除上面计算的矩形并再次遍历圆圈,仅绘制矩形内部的圆圈(可能会切断某些圆圈,但绘制适合矩形内部且不接触外部的所有内容)。

注意:两次迭代超过 1k+ 的圆圈几乎是瞬间的,你真正的问题在于圆圈的绘制(以及你奇怪的 x/y 存储机制)。图形 I/O 一直很慢,尤其是 Java 的处理方式。

进一步的优化是创建一个内存位图并在其中绘制你的矩形,然后在你的主表面上一次将它全部blit,以进一步减少闪烁(这是由于每次更新时重绘过程缓慢引起的)

于 2010-02-14T00:07:00.633 回答
1

在现代计算机上,几千个方法调用需要大约 10 微秒的时间,这绝对不是人类可察觉的延迟,更不用说“非常慢”了。

因此,您的性能问题的原因必须在其他地方 - 大概在 repaint() 中,这会导致容器的 paint() 被调用。如果这画了几个 1000 个圆圈,这可能需要将近一秒钟。

这就是为什么在优化之前,您应该始终测量性能瓶颈的实际位置。

于 2010-02-14T00:03:57.160 回答
1

每次调用都遍历你的整个圈子mouseDragged是一种难以置信的浪费时间。您拥有的一种选择是带头JTable开发方法,使您能够识别MouseEvent. 如果您知道列的宽度和行的高度,那么识别圆圈的单元格应该不难。

于 2010-02-14T00:04:35.833 回答
1

示例具有可移动、可调整大小的彩色节点,可以通过拖动边界矩形来选择这些节点。该实现通过显示矩形边框突出显示选定的节点。在下图中,绿色和黑色节点已被选中。相反,改变颜色将是draw()Node.

图形面板

于 2010-02-14T01:25:57.457 回答