QObjectPicker 在 Qt3DWidget 中没有收到悬停的 QMouseEvent
QObjectPicker not receiving hovering QMouseEvent in Qt3DWidget
我已经实现了一个 Qt3DWidget
,它通过让 Qt3D 绘制到屏幕外纹理并使用纹理的 ID 在 QOpenGLWidget
中的四边形上绘制,效果相当好。 QInputSettings
上的输入源设置为 this
,即小部件本身。
仍然存在的一个问题是鼠标悬停事件(未单击)未得到正确处理,并且 QObjectPicker
仅在悬停在对象上时从不触发其 moved
事件。另一方面,单击和拖动有效。几个小时以来,我试图追踪事件被吃掉的位置 - 我确信这发生在某个地方,因为单击和移动会发出 moved
事件。后者表明(在我看来)事件过滤器(a PickEventFilter
- private Qt3D class)已成功安装。一种失败情况是未安装事件过滤器。
现在我有点卡住了,因为试图找出事件结束的位置似乎是不可能的。我有 Qt 调试符号并单步执行代码(这有时有点错误,因为可能是由于代码优化)。我想通了 PickEventFilter
通过在这个方法中设置断点来移动鼠标时得到离开事件:
bool PickEventFilter::eventFilter(QObject *obj, QEvent *e)
{
Q_UNUSED(obj);
switch (e->type()) {
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseMove: {
QMutexLocker locker(&m_mutex);
m_pendingMouseEvents.push_back({obj, QMouseEvent(*static_cast<QMouseEvent *>(e))});
} break;
case QEvent::HoverMove: {
QMutexLocker locker(&m_mutex);
QHoverEvent *he = static_cast<QHoverEvent *>(e);
m_pendingMouseEvents.push_back({obj, QMouseEvent(QEvent::MouseMove,
he->pos(), Qt::NoButton, Qt::NoButton,
he->modifiers())});
} break;
case QEvent::KeyPress:
case QEvent::KeyRelease: {
QMutexLocker locker(&m_mutex);
m_pendingKeyEvents.push_back(QKeyEvent(*static_cast<QKeyEvent *>(e)));
}
default:
break;
}
return false;
}
还有 QWidgetWindow
中的这一行:
QApplicationPrivate::sendMouseEvent(receiver, &translated, widget, m_widget,
&qt_button_down, qt_last_mouse_receiver);
当 sendMouseEvent
发送移动事件时,它永远不会到达事件过滤器。唯一到达的是离开事件。当您使用 createWindowContainer
和 Qt3DWindow
时,鼠标事件起作用。我真的不知道有什么区别。
我认为 post 与此问题相关的代码不可行,但我希望你们中的一些人可以提供一些尝试的想法。
感谢评论中的 Scheff,我能够通过将 QWidget
class 中的 setMouseTracking
设置为 true 来使其工作。这阻止了悬停事件。
我已经实现了一个 Qt3DWidget
,它通过让 Qt3D 绘制到屏幕外纹理并使用纹理的 ID 在 QOpenGLWidget
中的四边形上绘制,效果相当好。 QInputSettings
上的输入源设置为 this
,即小部件本身。
仍然存在的一个问题是鼠标悬停事件(未单击)未得到正确处理,并且 QObjectPicker
仅在悬停在对象上时从不触发其 moved
事件。另一方面,单击和拖动有效。几个小时以来,我试图追踪事件被吃掉的位置 - 我确信这发生在某个地方,因为单击和移动会发出 moved
事件。后者表明(在我看来)事件过滤器(a PickEventFilter
- private Qt3D class)已成功安装。一种失败情况是未安装事件过滤器。
现在我有点卡住了,因为试图找出事件结束的位置似乎是不可能的。我有 Qt 调试符号并单步执行代码(这有时有点错误,因为可能是由于代码优化)。我想通了 PickEventFilter
通过在这个方法中设置断点来移动鼠标时得到离开事件:
bool PickEventFilter::eventFilter(QObject *obj, QEvent *e)
{
Q_UNUSED(obj);
switch (e->type()) {
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseMove: {
QMutexLocker locker(&m_mutex);
m_pendingMouseEvents.push_back({obj, QMouseEvent(*static_cast<QMouseEvent *>(e))});
} break;
case QEvent::HoverMove: {
QMutexLocker locker(&m_mutex);
QHoverEvent *he = static_cast<QHoverEvent *>(e);
m_pendingMouseEvents.push_back({obj, QMouseEvent(QEvent::MouseMove,
he->pos(), Qt::NoButton, Qt::NoButton,
he->modifiers())});
} break;
case QEvent::KeyPress:
case QEvent::KeyRelease: {
QMutexLocker locker(&m_mutex);
m_pendingKeyEvents.push_back(QKeyEvent(*static_cast<QKeyEvent *>(e)));
}
default:
break;
}
return false;
}
还有 QWidgetWindow
中的这一行:
QApplicationPrivate::sendMouseEvent(receiver, &translated, widget, m_widget,
&qt_button_down, qt_last_mouse_receiver);
当 sendMouseEvent
发送移动事件时,它永远不会到达事件过滤器。唯一到达的是离开事件。当您使用 createWindowContainer
和 Qt3DWindow
时,鼠标事件起作用。我真的不知道有什么区别。
我认为 post 与此问题相关的代码不可行,但我希望你们中的一些人可以提供一些尝试的想法。
感谢评论中的 Scheff,我能够通过将 QWidget
class 中的 setMouseTracking
设置为 true 来使其工作。这阻止了悬停事件。