Как ограничить QRubberBand в QLabel? - PullRequest
0 голосов
/ 16 января 2019

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

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

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

Я пытался использовать exitEvent () и 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 Ответ

0 голосов
/ 16 января 2019

Я думаю, что это ожидаемое поведение. Если вы хотите ограничить размеры резиновой ленты, просто зафиксируйте их в mouseMoveEvent override ...

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