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

默认只有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的友元类

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
QCustomPlot可以通过设置QCPAxisRect中的范围来实现这一功能。具体步骤如下: 1. 获取QCPAxisRect对象,可以通过QCustomPlot的axisRect()方法获取。 2. 设置QCPAxisRect对象中x轴和y轴的范围,通过QCPRange的setLower和setUpper方法设置。 3. 在QCustomPlot的mouseMoveEvent事件中,判断鼠标拖动的方向和距离,如果拖动到了负半轴,则将QCPAxisRect对象中x轴和y轴的范围设置为最小值,防止继续拖动到负半轴。 下面是一个示例代码: ```cpp void MyPlot::mouseMoveEvent(QMouseEvent *event) { if (mIsDragging) { QPoint delta = event->pos() - mDragStart; if (delta.x() < 0 && delta.manhattanLength() > 10) // 判断是否向左拖动 { double newLower = mPlot->xAxis->range().lower + delta.x() * mPlot->xAxis->range().size() / mPlot->axisRect()->width(); double newUpper = mPlot->xAxis->range().upper + delta.x() * mPlot->xAxis->range().size() / mPlot->axisRect()->width(); if (newLower < 0) { newLower = 0; newUpper = mPlot->xAxis->range().size(); } mPlot->xAxis->setRange(newLower, newUpper); } else if (delta.y() < 0 && delta.manhattanLength() > 10) // 判断是否向下拖动 { double newLower = mPlot->yAxis->range().lower + delta.y() * mPlot->yAxis->range().size() / mPlot->axisRect()->height(); double newUpper = mPlot->yAxis->range().upper + delta.y() * mPlot->yAxis->range().size() / mPlot->axisRect()->height(); if (newLower < 0) { newLower = 0; newUpper = mPlot->yAxis->range().size(); } mPlot->yAxis->setRange(newLower, newUpper); } mPlot->replot(); } } ``` 在这个示例代码中,我们通过判断鼠标拖动的方向和距离,来决定是否要设置QCPAxisRect对象中x轴和y轴的范围。如果拖动到了负半轴,我们就将范围设置为0~当前范围的大小,这样就可以防止继续拖动到负半轴了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值