我正在将应用程序从 MFC 迁移到 Qt。
MFC 应用程序将使用 GDI 调用来构建窗口(基本上是一个图表)。它将绘制到内存位图后台缓冲区,然后将 BitBlt 绘制到屏幕上。然而,Qt 已经做了双缓冲。
当用户在图表中单击并拖动时,我希望窗口的该部分被反转。
我想找到最好的方法来做到这一点。有没有办法做一些像从小部件的后台缓冲区而不是屏幕抓取的东西?...也许是 BitBlt(..., DST_INVERT) 等价物?
我在 QPainter 中看到了 setCompositionMode(),但文档说这只适用于在 QImage 上操作的画家。(否则,我可以使用精美的合成模式将实心矩形图像合成到我的小部件上,以获得类似反转效果的效果)
我可以做与 MFC 相同的事情,绘制到 QImage 后台缓冲区......但我读到硬件加速可能无法以这种方式工作。重新实现 Qt 中已经提供给您的双缓冲似乎是一种浪费。我也不太确定关闭小部件的双缓冲可能会产生什么副作用(以避免三重缓冲)。
有一次,我有一个令人费解的 QPixmap::grabWidget() 调用,并带有防止递归的标志来保护它,但这会将所有内容渲染两次,并且显然比仅绘制到 QImage 更糟糕。(并且在文档中特别警告过)
我是否应该放弃并将所有内容绘制到 QImage 上,就像我在 MFC 中所做的那样?
编辑:
好的,QPixmap 画家的运行速度与现在的直接运行速度大致相同。因此,使用 QPixmap 后台缓冲区似乎是最好的方法。
解决方案对我来说并不明显,但如果我查看更多示例(例如 Ariya 的 Monster 演示),我可能会按照预期的方式对其进行编码,并且效果会很好。
这就是区别。我看到了使用这个的帮助系统演示:
QPainter painter(this)
在paintEvent() 的开始。因此,我似乎很自然地认为,将缓冲区加倍到 QPixmap 然后在屏幕上绘制,您需要这样做:
QPainter painter(&pixmap);
QPainter painterWidget(this);
... draw using 'painter' ...
painterWidget.drawPixmap(QPoint(0,0), pixmap);
实际上,您显然应该这样做:
QPainter painter;
painter.begin(&pixmap);
... draw using 'painter' ...
painter.end();
painter.begin(this);
painter.drawPixmap(QPoint(0,0), pixmap);
painter.end();
我可以看到我的方式同时有两个活跃的画家。我不完全确定为什么它更快,但直觉上我更喜欢后者。它是一个单一的 QPainter 对象,一次只做一件事。也许有人可以解释为什么第一种方法不好?(就 Qt 渲染引擎中的错误假设而言)