1

我是新手C++,这是在 Stack Overflow 上Qt的第一篇文章。Visual Studio

如果这是一个重复的问题,我提前道歉,我尝试搜索类似的问题但找不到。如果这是一个重复的问题,请告诉我,我将删除它。

我正在尝试使用QWidget::paintEvent(). 我正在绘制的线图实际上是一个QPainterPath. 我想检测鼠标何时悬停在我的线图上,因此我在鼠标光标所在的位置创建了一个小矩形,并使用bool QPainterPath::intersects()函数检测该矩形何时与我的线图相交。问题是即使我的鼠标不在我的线图上,这个函数也会返回 true。在图像 1中(我还不允许嵌入图像)我的线图是粗黑色曲线,bool QPainterPath::intersects()即使我的光标位于黄色区域上也返回 true。根据 Qt 文档,这是因为:

如果构成矩形的任何线与路径的一部分相交,或者矩形的任何部分与路径所包围的任何区域重叠,则存在交叉点。

没有任何封闭区域是不可能的,QPainterPath因为 Qt 只为QPainterPath:Qt::OddEvenFillQt::WindingFill. (老实说,我觉得这很烦人,因为开放路径是一系列端到端连接的线段,如果有人想包围一个区域,他们可以使用QPainterPath::lineTo()QPainterPath::moveTo()函数轻松连接第一个点和最后一个点)

无论如何,我决定变得更聪明,并在我的线图上方几个像素和在我的线图下方几个像素处Qt画了两个额外QPainterPath的。图 2显示了这 3 个线图,红色的是,黑色的是实线图,绿色的是。我想我可以使用以下代码检测到交叉点:pathUppathDnpathUppathDnQWidget::mouseMoveEvent()

// cRect: Rectangle at mouse cursor position
if((pathUp.intersects(cRect) && (!pathDn.intersects(cRect))) || ((!pathUp.intersects(cRect)) && pathDn.intersects(cRect)))
{
    qDebug() << "Intersects";
}

但这仍然会产生错误的结果,因为现在封闭区域不同了,如图3所示,绿色区域是 的封闭区域,pathDn红色区域是 的封闭区域pathUp。粗黑曲线再次是我想要检测鼠标悬停在其上的线图。这个封闭区域不受 的Qt::setFillRule影响QPainterPath

更令人沮丧的是,我使用QPolygonF而不是QPainterPathon尝试了这种技术QWidget,结果完全一样。我也尝试过QGraphicsView,我曾经QGraphicsPathItem在那里创建我的线图,然后使用QGraphicsScene::focusItemChanged()信号来检测我何时点击我的线图。当我的光标位于封闭区域上时,它再次产生了检测点击的相同结果。我不想创建一个自定义QGraphicsItem(除非我绝对必须)只是为了重新实现它hoverEnterEvent()和方法,因为Qt Docs 中解释了对的hoverLeaveEvent()限制:boundingRect()QGraphicsItem

QGraphicsScene 期望所有项目 boundingRect() 和 shape() 保持不变,除非它被通知。如果您想以任何方式更改项目的几何图形,您必须首先调用 prepareGeometryChange() 以允许 QGraphicsScene 更新其簿记。

由于我实时绘制绘图,因此boundingRect()会非常频繁地更改(> 20 Hz),这会给软件带来额外的计算负担。有什么方法可以在不创建自定义的情况下解决我的问题QGraphicsItem

PS 多年来,每当我遇到困难时,我一直在使用 Stack Overflow。我只是从来没有在这里开过账户,因为我从来不需要发布任何东西。你们是最棒的,我很高兴成为这个社区的一员!

4

0 回答 0