获取鼠标下QWidget像素颜色的最快方法是什么?

4

我需要在QWidget(面包板)的mouseMoveEvent中获取鼠标下方像素的颜色。目前我有以下代码->

void Breadboard::mouseMoveEvent(QMouseEvent *e)
{
    QPixmap pixmap = QPixmap::grabWindow(winId());
    QRgb color = pixmap.toImage().pixel(e->x(), e->y());
    if (QColor(color) == terminalColor)
        QMessageBox::information(this, "Ter", "minal");
}

请查看以下(缩小)屏幕截图-

enter image description here

当用户将鼠标移动到面包板上时,孔应该用一些不同的颜色(如红色圆圈)突出显示。当鼠标退出时,应恢复先前的颜色(灰色)。因此,我需要执行以下步骤:
  1. 获取鼠标下方的颜色
  2. 根据颜色填充孔。(使用颜色区分不同的孔)
  3. 在鼠标离开时,恢复颜色。由于有导线穿过孔,所以我不能仅更新小矩形(孔)。
这样做最快的方法是什么?我尝试提取颜色,但我的上面的代码中的消息框从未显示。此外,我怀疑我的现有代码是否足够快,因为您在面包板上移动鼠标的速度很快。 注意-我能够使用wxWidgets框架完成此操作。但由于某些问题,该项目停滞了。现在我正在使用Qt重新编写它。欢迎查看代码https://github.com/vinayak-garg/dic-sim
2个回答

5
在Qt中,做这件事的“惯用”方式与您描述的完全不同。您将使用Graphics View Framework来完成此类操作。

Graphics View提供了一个表面来管理和与大量自定义的2D图形项交互,以及一个视图小部件来可视化项目,并支持缩放和旋转。

您需要为面包板中的“单元格”定义自己的QGraphicsItem类型,以通过更改其颜色响应悬停进入/离开事件。单元格之间的连接(电线、电阻器或其他)也将具有自己的图形项类型,具有您所需的功能。
以下是一个简单而粗略的示例。它生成一个50x50的绿色单元格网格,当鼠标悬停在上面时变为红色。
#include <QtGui>

class MyRect: public QGraphicsRectItem
{
    public:
        MyRect(qreal x, qreal y, qreal w, qreal h)
            : QGraphicsRectItem(x,y,w,h) {
            setAcceptHoverEvents(true);
            setBrush(Qt::green);
        }
    protected:
        void hoverEnterEvent(QGraphicsSceneHoverEvent *) {
            setBrush(Qt::red);
            update();
        }
        void hoverLeaveEvent(QGraphicsSceneHoverEvent *) {
            setBrush(Qt::green);
            update();
        }
};

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    QGraphicsScene scene;
    for (int i=0; i<50; i++)
        for (int j=0; j<50; j++)
            scene.addItem(new MyRect(10*i, 10*j, 8, 8));

    QGraphicsView view(&scene);
    view.show();
    return app.exec();
}

您可以修改悬停事件处理程序,与您的“主窗口”或“控制器”通信,指示当前鼠标下方的内容,以便更新标题、图例框或工具面板。


+1 谢谢!那么我可以将 Breadboard 作为 QGraphicsScene 对象而不是将其作为 QWidget 吗? - Vinayak Garg
是的,那听起来像是一个选项。如果您需要自定义行为,可以为“单元格”/孔和“条形”/线构建自定义类。然后将它们添加到您的面包板场景中。(即使在场景中有大量项目,这一切都非常快速。) - Mat

2
为了获得最佳速度,将你感兴趣的部分小部件渲染到 QPaintDevice(如 QPixmap)中。尝试如下操作:
void Breadboard::mouseMoveEvent(QMouseEvent *e)
{
    // Just 1 pixel.
    QPixmap pixmap(1, 1);

    // Target coordinates inside the pixmap where drawing should start.
    QPoint targetPos(0, 0);

    // Source area inside the widget that should be rendered.
    QRegion sourceArea( /* use appropriate coordinates from the mouse event */ );

    // Render it.
    this->render(&pixmap, targetPos, sourceArea, /* look into what flags you need */);

    // Do whatever else you need to extract the color from the 1 pixel pixmap.
}

如果你愿意重构应用程序以使用图形视图API,那么Mat的答案更好。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接