简体   繁体   中英

Qt Troubles with painting selection box

I'm having troubles forcing a repaint/update of my Qt Widget (it extends the QGraphicsView class). What I want is a rectangular selection box to be drawn which will highlight the target selection area as the user presses and moves the mouse.

The basic workflow:

  1. MousePressEvent sets the making_selection_box flag, and stores the start point (working).
  2. MouseMoveEvent checks to see if the display needs to be updated. If it does, it tries to do so (not working).
  3. MouseReleaseEvent handles gets the resulting selection box and handles it accordingly. making_selection_box is reset. Screen should be updated to remove the selection box artifact (not working).

The overrided mouseMoveEvent:

void QSchematic::mouseMoveEvent(QMouseEvent *event)
{
    if(making_selection_box)
    {
        // get selection box
        qDebug() << "updating selection box";
        curr_selection_end = event->pos();
        repaint(box(drag_select_start, curr_selection_end));
    }
    // propogate event
    QGraphicsView::mouseMoveEvent(event);
}

My overrided paintEvent:

void QSchematic::paintEvent(QPaintEvent *event)
{
    qDebug() << "paintEvent";
    if(making_selection_box)
    {
        qDebug() << "drawing selection box";
        QPainter painter(viewport());
        painter.setPen(Qt::black);
        painter.drawRect(box(drag_select_start, curr_selection_end));
        painter.end();
    }
    // propogate event
    QGraphicsView::paintEvent(event);
}

Box is just a small helper function I wrote to create the correct QRect for different selection box start/end points.

static QRect box(const QPoint& p1, const QPoint &p2)
{
    int min_x = p1.x();
    int min_y = p1.y();
    int max_x = p2.x();
    int max_y = p2.y();
    if(max_x < min_x)
    {
        max_x = min_x;
        min_x = p2.x();
    }
    if(max_y < min_x)
    {
        max_y = min_y;
        min_y = p2.y();
    }
    return QRect(min_x, min_y, max_x - min_x, max_y - min_y);
}

I've verified that mouseMoveEvent is being triggered correctly when the user presses a button and moves the mouse around.

I've also verified that paintEvent is being called by the system when I perform various standard operations such as resize the window, minimize/maximize it, etc.

I've verified that the method I'm using to paint to my widget will work correctly with other paintEvent triggers, I just can't manage to trigger a repaint in my code.

I've also tried forcing the update by using the update() method instead of repaint() , but no luck.

As a side note, am I going about creating this selection box functionality the wrong/hard way? Is there a better way to get a selection box without having to manually implement the mouse listeners and painting code?

I'm testing with Qt 4.8.4 on Windows 7 x64, using the Visual Studio 2010 MSVC compiler.

After looking through the QGraphicsScene API I found an easy workaround for having to manually manage the selection box: The drag mode needs to be set to RubberBandDrag .

edit:

To further expand my answer which allows painting on the QGraphicsView for other purposes, it's the viewport which needs to receive the update/redraw, not my QGraphicsView object.

void QSchematic::mouseMoveEvent(QMouseEvent *event)
{
    if(making_selection_box)
    {
        // get selection box
        qDebug() << "updating selection box";
        curr_selection_end = event->pos();
        viewport()->repaint(box(drag_select_start, curr_selection_end));
    }
    // propogate event
    QGraphicsView::mouseMoveEvent(event);
}

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