Как ограничить QRubberBand в QLabel?

Я создаю приложение Qt5, которое позволяет пользователю рисовать резинкой с помощью мыши над изображением, чтобы выбрать определенную область изображения для дальнейшей обработки.

Я получил свой код, чтобы позволить пользователю только начать рисовать резинку, создав подкласс QLabel для пользовательского класса (frame_displayer), который mousePressEvent() переопределяет и, таким образом, вызывается только тогда, когда нажатие мыши происходит внутри пользовательского классифицированного виджета.

Проблема в том, что когда первоначальный щелчок находится внутри frame_displayer, mouseMoveEvent (), функция, которую я использую для соответствующего изменения размера резиновой ленты, продолжает вызываться, даже когда курсор мыши перетаскивается за пределы frame_displayer.

Я попытался с помощью метода leftEvent () и enterEvent() управлять логическим флагом класса, на который могут опираться коды внутри mouseMoveEvent, чтобы узнать, находится ли курсор в виджете. Однако оба метода leftEvent () и enterEvent() вызываются только тогда, когда кнопка мыши не удерживается, что делает их бесполезными для ограничения резиновой ленты.

Кроме того, underMouse() всегда возвращает true по неизвестной мне причине.

Сегмент 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";
}

Заранее спасибо!

1 ответ

Решение

Я думаю, что это ожидаемое поведение. Если вы хотите ограничить размеры резиновой ленты, просто зажмите их 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());
            }
        }
    }
}
Другие вопросы по тегам