简体   繁体   中英

What is the fastest way to get QWidget pixel color under mouse?

I need to get the color of pixel under mouse, inside mouseMoveEvent of a QWidget (Breadboard). Currently I have this code->

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");
}

Take a look at (scaled down) screenshot below-

在此输入图像描述

When user moves his mouse on breadboard, the hole should get highlighted with some different color (like in red circle). And when the mouse exits, the previous color (grey) should be restored. So I need to do following steps-

  1. Get color under mouse
  2. According to color, floodfill the hole. (Different holes are distinguished using color)
  3. On mouse out, restore the color. There would be wires going over holes, so I can't update the small rectangle (hole) only.

What is the fastest way of doing this? My attempt to extract color is not working ie the Message box in my above code never displays. Moreover I doubt if my existing code is fast enough for my purpose. Remember, how fast you will be moving your mouse on breadboard.

Note - I was able to do this using wxWidgets framework. But due to some issues that project got stalled. And I am rewriting it using Qt now.
You are invited to look at code https://github.com/vinayak-garg/dic-sim

The "idiomatic" way of doing this in Qt is completely different from what you're describing. You'd use the Graphics View Framework for this type of thing.

Graphics View provides a surface for managing and interacting with a large number of custom-made 2D graphical items, and a view widget for visualizing the items, with support for zooming and rotation.

You'd define your own QGraphicsItem type for the "cells" in the breadboard that would react to hover enter/leave events by changing their color. The connections between the cells (wires, resistors, whatever) would also have their own graphics item types with the features you need for those.

Here's a quick and dirty example for you. It produces a 50x50 grid of green cells that become red when the mouse is over them.

#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();
}

You could modify the hover event handlers to talk to your "main window" or "controller" indicating what's currently under the mouse so you can update your caption, legend box or tool palette.

For best speed, render only the portion of the widget you're interested in into a QPaintDevice (like a QPixmap). Try something like this:

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.
}

Mat's answer is better if you're willing to refactor your application to use the graphics view API.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM