Qt

QCustomPlot之设置鼠标形状(十三)

2020-04-09  本文已影响0人  梁如风

默认只有QWidget才有setCursor接口,QCustomPlot也没有为我们扩展它,所以我们自己增加可以设置鼠标形状的接口

效果图
void QCPLayerable::setCursor(const QCursor &cursor)
{
    mHasCursor = true;  // 新增的bool成员变量
    mCursor = cursor;    // 新增的QCursor成员变量
    if (mParentPlot && mParentPlot->underMouse()) {
        const auto layerableList = mParentPlot->layerableListAt(mParentPlot->mapFromGlobal(QCursor::pos()), false);
        for (auto *layerable : layerableList) {
            if (layerable->hasCursor()) {
                QMetaObject::invokeMethod(mParentPlot, "setViewportCursor",
                                          Q_ARG(QCursor, layerable->cursor()));
                break;
            }
        }
    }
}

void QCPLayerable::unsetCursor()
{
    if (!mHasCursor || !mParentPlot)
        return;

    mHasCursor = false;
    if (mParentPlot->underMouse() && mParentPlot->layerableAt(mParentPlot->mapFromGlobal(QCursor::pos()), false) == this) {
        QMetaObject::invokeMethod(mParentPlot, "unsetViewportCursor");
    }
}

同时为QCPLayerable新增鼠标进入和离开事件

virtual void hoverEnterEvent(QHoverEvent *event) { Q_UNUSED(event) }
virtual void hoverLeaveEvent(QHoverEvent *event) { Q_UNUSED(event) }

我们主要在QCustomPlot中的mouseMoveEvent事件中处理鼠标形状的改变以及鼠标进入和离开QCPLayerable事件的传递

    event->accept();   // 以上为源码内容

    auto list = layerableListAt(event->pos(), false);
    QCPLayerable *hoveredLayerable = list.isEmpty() ? nullptr : list.first();
    if (hoveredLayerable) {
        if (mLastHoverLayerable != hoveredLayerable) {
            if (mLastHoverLayerable) {
                auto *item = static_cast<QCPAbstractItem *>(mLastHoverLayerable);
                if (item) emit hoverLeaveItem(item);
                QHoverEvent hoverEvent(QEvent::HoverLeave, QPointF(-1, -1), event->pos(), event->modifiers());
                mLastHoverLayerable->hoverLeaveEvent(&hoverEvent);
            }

            mLastHoverLayerable = hoveredLayerable;
            auto *item = static_cast<QCPAbstractItem *>(mLastHoverLayerable);
            if (item) emit hoverEnterItem(item);
            QHoverEvent hoverEvent(QEvent::HoverEnter, event->pos(), QPointF(-1, -1), event->modifiers());
            mLastHoverLayerable->hoverEnterEvent(&hoverEvent);
        }
    }

    // 以后可以优化
    foreach (auto *layerable, list) {
        if (layerable->hasCursor()) {
            setViewportCursor(layerable->cursor());
            return;
        }
    }

    if (mLastHoverLayerable) {
        auto *item = static_cast<QCPAbstractItem *>(mLastHoverLayerable);
        if (item) emit hoverLeaveItem(item);
        QHoverEvent hoverEvent(QEvent::HoverLeave, QPointF(-1, -1), event->pos(), event->modifiers());
        mLastHoverLayerable->hoverLeaveEvent(&hoverEvent);
        mLastHoverLayerable = nullptr;
    }

    if (mHasStoredOriginalCursor) {
        mHasStoredOriginalCursor = false;
        setCursor(mOriginalCursor);
    }

设置和恢复QCustomPlot的鼠标形状,注意这两个函数要声明为Q_INVOKABLE

void QCustomPlot::setViewportCursor(const QCursor &newCursor)
{
    if (!mHasStoredOriginalCursor) {
        mHasStoredOriginalCursor = true;
        mOriginalCursor = cursor();
    }
    setCursor(newCursor);
}

void QCustomPlot::unsetViewportCursor()
{
    const auto layerableList = layerableListAt(mapFromGlobal(QCursor::pos()), false);
    foreach (auto *layerable, layerableList) {
        if (layerable->hasCursor()) {
            setViewportCursor(layerable->cursor());
            return;
        }
    }

    if (mHasStoredOriginalCursor) {
        mHasStoredOriginalCursor = false;
        setCursor(mOriginalCursor);
    }
}

我们可以通过设置setSelectionTolerance设置QCustomPlot的选择误差范围来决定QCustomPlot的鼠标点击(悬浮)行为

注意要将QCPLayerable设置为QCustomPlot的友元类

上一篇下一篇

猜你喜欢

热点阅读