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