Qt QGraphicsView mouseMoveEvent 不间断工作

问题描述 投票:0回答:1

由于某种原因,在 QGraphicsScene 类中使用 addWidget 函数会使相关的 QGraphicsView 小部件接收 mouseMoveEvents,而无需按下鼠标按钮并关闭鼠标跟踪。

MyView.h:

#pragma once

#include <qgraphicsview>
#include <qevent>
#include <qgraphicsscene>
class MyView : public QGraphicsView // subclassing QGraphicsView
{
    Q_OBJECT
protected:
    void mouseMoveEvent(QMouseEvent* event);


public:
    MyView(QGraphicsScene* scene, QWidget *parent);
    ~MyView();
};

MyView.cpp:

#include "MyView.h"

MyView::MyView(QGraphicsScene* scene, QWidget* parent)
    : QGraphicsView(scene, parent)
{}

void MyView::mouseMoveEvent(QMouseEvent* event)
{
    qDebug() << this->hasMouseTracking(); // indicating that the event goes on 
                                              // even though I dont't press any buttons
                                              // and mouse tracking is disabled by default
}

MyView::~MyView()
{}

QMainWindow.cpp:

QVBoxLayout* layout = new QVBoxLayout();
ui.centralWidget->setLayout(layout);
QGraphicsScene* scene = new QGraphicsScene();
scene->addWidget(new QWidget());
MyView* v = new MyView(scene, ui.centralWidget);
layout->addWidget(v);

只有在场景中添加 QWidget 或其子类后才会发生这种情况。 Qt版本是6.7.0

c++ qt qgraphicsview qgraphicsscene qt6
1个回答
0
投票

只有在场景中添加 QWidget 或其子类后才会发生这种情况

这就是它发生的原因。
只要场景中的项目需要鼠标跟踪,鼠标跟踪就会自动启用,这对于通过 QGraphicsProxyWidgets 添加的小部件是隐式的。

默认情况下,QWidget 不会设置

mouseTracking
属性,该属性通常为
false
(禁用),并且不会为其更改提供任何通知信号。

实际上,许多小部件将该属性设置为

true
:例如,在启用了清除按钮的 QLineEdit 中更改鼠标光标,或者显示超链接的 QLabel,或者在视图中显示悬停的项目。

为了通过代理将

Enter
Leave
事件正确传播到小部件,还需要正确的鼠标移动跟踪。

因此,QGraphicsScene 所做的假设是,每当将

any QGraphicsProxyWidget 添加到其中时,即使没有按下鼠标按钮,其小部件也可能接收鼠标移动事件,因此它会自动将 mouseTracking 属性设置为

true 
对于所有显示它的视图。如果将场景添加到视图,并且它已经包含 QGraphicsProxyWidgets,则该属性会类似地自动设置。
代理项最终将根据其 

mouseTracking

属性决定事件是否实际发送到小部件。

请注意,小部件可能是一个复杂的小部件(例如,一个容器,甚至是一个“窗口”),因此拥有一个通知器信号毫无意义,因为每次其子树发生更改时都很难传播和管理。

因此,结论是,每当将任何

QGraphicsProxyWidget

添加到场景中(包括使用

scene::addWidget()
)时,连接到该场景的视图将始终使用鼠标跟踪(即使这些项目被删除并且场景被清除后) ,并且从那一刻起总会导致
mouseMoveEvent()
触发,除非手动调用
setMouseTracking(false)
这需要在视图中正确实现

mouseMoveEvent()

:根据您的需求(顺便说一句,您没有澄清),您可能需要首先调用基本实现,这可能会将事件中继到场景如果 QGraphicsProxyWidget 中的小部件

contained
首先执行了该事件,则接受/忽略该事件,并最终在这种情况下检查event::isAccepted()
或者,您可能只想在将事件映射到场景并检查该场景位置是否有最上面的 QGraphicsProxyWidget 项之后才处理该事件。

无论如何,您所面临的行为不仅是预期的,而且从根本上来说是必需的。

© www.soinside.com 2019 - 2024. All rights reserved.