简体   繁体   English

如何在QLabel中限制QRubberBand?

[英]How to constrain a QRubberBand within a QLabel?

I am building a Qt5 application that allows a user to draw a rubberband with his mouse over an image, to select certain area of the image for further processing. 我正在构建一个Qt5应用程序,该应用程序允许用户用鼠标在图像上绘制橡皮筋,以选择图像的某些区域以进行进一步处理。

I got my code to only allow the user to start drawing the rubberband, by subclassing a QLabel to a custom class (frame_displayer) which mousePressEvent() is overridden and thus be only invoked when the mouse press happens within the custom classed widget. 通过将QLabel子类化为自定义类(frame_displayer),我的代码只允许用户开始绘制橡皮筋,该类将覆盖mousePressEvent() ,因此仅在自定义分类的小部件内发生鼠标按下时才被调用。

The problem is that when the initial click is inside the frame_displayer, mouseMoveEvent() , the function that I use to change the rubberband size accordingly, keeps getting called even when the mouse cursor has been dragged outside of the frame_displayer. 问题是,当初次单击在frame_displayer内部时,即使将鼠标指针拖到frame_displayer之外,我用来相应更改橡皮筋大小的函数mouseMoveEvent()仍会被调用。

I have tried using leaveEvent() and enterEvent() to control a class boolean flag that codes inside mouseMoveEvent could rely on to know whether the cursor is still within the widget. 我试过使用LeaveEvent()enterEvent()来控制类boolean标志,mouseMoveEvent内部的代码可以依靠该标志来知道光标是否仍在小部件内。 However, both leaveEvent() and enterEvent() are only called while a mouse button is not being held, thus rendering them no use for constraining the rubberband. 但是,仅在不按住鼠标按钮的情况下才调用LeaveEvent()enterEvent() ,因此使它们对约束橡皮筋没有用处。

Also, the underMouse() always return true, for a reason unknown to me. 此外, 出于我未知的原因, underMouse()始终返回true。

Segment of frame_displayer.cpp frame_displayer.cpp的段

frame_displayer::frame_displayer(QWidget * parent) : QLabel(parent)
{
    _rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
}

void frame_displayer::mousePressEvent(QMouseEvent *event)
{
    _lastClickedBtn = event->button();
    if (_lastClickedBtn == Qt::LeftButton)
    {
        _mouseOriginClickPoint = event->pos();
        _rubberBand->setGeometry(QRect(_mouseOriginClickPoint, _mouseClickPoint));
        _rubberBand->show();
    }
}

void frame_displayer::mouseMoveEvent(QMouseEvent *event)
{
    if(_rubberBand != nullptr)
    {
        if (this->underMouse())
        {
            if (_lastClickedBtn == Qt::LeftButton)
            {
                QPoint mouseCurrentPoint = event->pos();
                _rubberBand->setGeometry(QRect(_mouseOriginClickPoint, mouseCurrentPoint).normalized());
            }
        }
    }
}

void frame_displayer::mouseReleaseEvent(QMouseEvent *event)
{
    _mouseOriginClickPoint = QPoint();
    _lastClickedBtn = Qt::MidButton;
    if(_rubberBand != nullptr)
    {
        _rubberBand->hide();
        _rubberBand->clearMask();
    }
}

void frame_displayer::leaveEvent(QEvent *event)
{
    qDebug() << "Leaving";
}

void frame_displayer::enterEvent(QEvent *event)
{
    qDebug() << "Entering";
}

Thanks in advance! 提前致谢!

I think that's the expected behaviour. 我认为这是预期的行为。 If you want to limit the extents of the rubber band then simply clamp them in the mouseMoveEvent override... 如果要限制橡皮筋的范围,则只需将其夹在mouseMoveEvent覆盖中即可...

void frame_displayer::mouseMoveEvent(QMouseEvent *event)
{
    if(_rubberBand != nullptr)
    {
        if (this->underMouse())
        {
            if (_lastClickedBtn == Qt::LeftButton)
            {
                QPoint mouseCurrentPoint = event->pos();

                /*
                 * Clamp mouseCurrentPoint to the QRect of this widget.
                 */
                auto clamp_rect = rect();
                mouseCurrentPoint.rx() = std::min(clamp_rect.right(), std::max(clamp_rect.left(), mouseCurrentPoint.x()));
                mouseCurrentPoint.ry() = std::min(clamp_rect.bottom(), std::max(clamp_rect.top(), mouseCurrentPoint.y()));
                _rubberBand->setGeometry(QRect(_mouseOriginClickPoint, mouseCurrentPoint).normalized());
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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