我已经开始学习Qt,并尝试提高我的基本C ++技能。 在GraphicsScene中,我尝试使用鼠标绘制一条线(鼠标事件)。 当我开始在GraphicsScene中绘制一条线时,从原点绘制一条细虚线,在点击第二个点之前,我先点击当前鼠标位置并用鼠标移动。为了擦除它,我用黑色绘制它。如果我将鼠标悬停在已经绘制的线条上,您将看到它们上面的黑色绘制线条。为了在不留下标记的情况下绘制它,在GraphicsScene上进行XOR操作会派上用场,或者如果我可以在不同的层中绘制而不触及另一层则可以很方便。但我还不知道该怎么做。该示例位于https://github.com/JackBerkhout/QT_Draw001 在line.cpp中是函数setLineP2(int x,int y),它绘制并擦除那条细虚线。 有人可以帮帮我吗?
答案 0 :(得分:0)
主要的错误观念是将QGraphicsScene
视为某种位图:它不是!它是可以自我渲染的项目集合,以及它们的空间索引。在场景中,如果您想要删除/隐藏某些内容,您不得过度删除 - 而只需根据需要删除/隐藏相关项目。场景将处理所有细节 - 这就是它的用途
此时你必须忘记GDI。你不是在这里画上原始DC。即使使用原始GDI,你也不想在窗口的DC上绘画那样闪烁,你应该在位图上绘制并将位图blit到窗口。
例如,您的eraseScene
方法在场景顶部添加了一个矩形,浪费了内存和资源,因为所有以前的项都被保留(您可以迭代它们),而它应该做的只是{{ 1}}场景(或其等价物):
clear
VS。正确的:
void MainWindow::eraseScreen(void)
{
[...]
scene->addRect(0, 0, width()+1000, height()+1000, pen, brush);
}
下面是一个完整的示例,它近似于您在代码中可能要执行的操作。 它长达120行。由于您的代码如此错综复杂,有点难以弄清楚您究竟打算做什么 - 在问题中以简单的术语描述确切行为很有用。
该示例使用void MainWindow::eraseScreen(void)
{
scene->clear();
}
来保留QPainterPath
呈现MoveTo
和LineTo
元素的列表。它还使用QPainterPathItem
来显示瞬态线。
QGraphicsLineItem
用于包含修改路径的上下文,并确保维护正确的前后条件。即:
由于MyScene::PathUpdater
是隐式共享的,因此您应该清除QPainterPath
所持有的路径,以避免不必要的隐式副本。在修改QGraphicsPathItem
之前,这是必要的前提条件。
修改m_path
后,必须更新路径项,并发出新状态。
以下其他要点值得注意:
按值保存成员会导致显着缺少任何内存管理代码(!) - 编译器会为我们完成所有操作。您无法在任何地方找到单个m_path
或new
。它们不是必需的,我们不会为不手动执行此操作而支付额外费用。现代C ++看起来应该是这样的。
显示delete
和MainWindow
之间的明确分割。 MyScene
对MainWindow
的具体内容一无所知,反之亦然。 MyScene
中的代码充当两者之间的适配器。
利用C ++ 11。
SO测试用例和示例所需的简洁风格:学习它最好将其全部保存在一个文件中,以便轻松查看代码的所有部分。它只有120行,而不是文件分割的两倍多。我们的大脑利用参考的地方。通过拆分代码,你会让自己更难理解。