Qt - 如何在 Qt3DWindow 上获取鼠标事件
Qt - How to get mouse events on Qt3DWindow
我想在 Qt3D Window 上获取鼠标事件(如鼠标位置),每次我在 window.
中单击时
我看过 (also the same question on this forum) 但我的 Qt3DWindow 不在任何小部件中,所以我认为我不需要 EventFilter。
我刚刚开始学习 C++ 和 Qt,所以我正在努力使最简单的程序成为可能。在下面的代码中(我所有的程序都在这段代码中),我想在Qt3DWindow中每次点击时都得到鼠标位置,但我什至无法在每次点击时得到调试消息。
据我了解,mouseMoveEvent
函数仅在程序执行时调用一次。如果 Qt 中有这样的东西,我将如何在主循环中调用这个函数?
我需要做这样的事情吗?
Qt3DInput::QMouseDevice *mouse = new Qt3DInput::QMouseDevice(scene);
但是我该如何使用它呢?
#include <QGuiApplication>
#include <Qt3DCore/QEntity>
#include <Qt3DRender/QCamera>
#include <Qt3DRender/QCameraLens>
#include <Qt3DCore/QTransform>
#include <Qt3DCore/QAspectEngine>
#include <Qt3DInput/QInputAspect>
#include <Qt3DRender/QRenderAspect>
#include <Qt3DExtras/QForwardRenderer>
#include <Qt3DExtras/QPhongMaterial>
#include <Qt3DExtras/QGoochMaterial>
#include <Qt3DExtras/QSphereMesh>
#include <Qt3DExtras/QCuboidMesh>
#include <QMouseEvent>
#include <Qt3DInput/QMouseDevice>
#include <Qt3DInput/QMouseHandler>
#include <Qt3DInput/QMouseEvent>
#include <QDebug>
#include "qt3dwindow.h"
void mouseMoveEvent(Qt3DInput::QMouseEvent *event);
Qt3DCore::QEntity *createScene()
{
// Root entity
Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity;
// Material
//Qt3DRender::QMaterial *material = new Qt3DExtras::QPhongMaterial(rootEntity);
Qt3DRender::QMaterial *material = new Qt3DExtras::QGoochMaterial(rootEntity);
//Cube
Qt3DCore::QEntity *cubeEntity = new Qt3DCore::QEntity(rootEntity);
Qt3DExtras::QCuboidMesh *cubeMesh = new Qt3DExtras::QCuboidMesh;
cubeEntity->addComponent(cubeMesh);
cubeEntity->addComponent(material);
return rootEntity;
}
int main(int argc, char* argv[])
{
QGuiApplication app(argc, argv);
Qt3DExtras::Qt3DWindow view;
Qt3DCore::QEntity *scene = createScene();
// Camera
Qt3DRender::QCamera *camera = view.camera();
camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
camera->setPosition(QVector3D(5.0, 5.0, 5.0f));
camera->setViewCenter(QVector3D(0, 0, 0));
Qt3DInput::QMouseEvent *e;
mouseMoveEvent(e);
view.setRootEntity(scene);
view.show();
return app.exec();
}
void mouseMoveEvent(Qt3DInput::QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
qDebug() << "ok";
}
}
通常 "mouseMoveEvent" 与 Qwidget 绑定。
这是Qt3DInput::QmouseEvent
的源代码:
class QT3DINPUTSHARED_EXPORT QMouseEvent : public QObject {
Q_OBJECT
private:
QT_PREPEND_NAMESPACE(QMouseEvent) m_event;
};
m_event已经包含了您鼠标的信息,应该会自动处理。
Mouse events occur when a mouse button is pressed or released inside a
widget, or when the mouse cursor is moved.
所以,我认为您不需要创建新的 Qt3DInput::QMouseDevice
。你不应该这样做 Qt3DInput::QMouseEvent *e
;因为小部件会自动获取它。
我不知道如何在不在 Qwidget 中覆盖它的情况下使用 mouseEvent,Qt3DExtras::Qt3DWindow 视图应该包含默认值 mouseMoveEvent()
。
如果你只想打印一个"ok",我建议你不要写任何关于mouseMoveEvent()
的东西。如果您希望鼠标移动时发生某些事情,您应该覆盖视图的 mouseMoveEvent()
.
你在这里做错了几件事。
首先,我建议你subclass Qt3DWindow
并将场景的设置代码放在那里。这毕竟是意见责任。主体应该保持简单和干净。当然不要在视图中放置任何重要的逻辑,但设置代码应该在那里(坚持模型-视图-控制器)。
接下来,您当然不会收到任何调试消息,因为您在那里进行了检查
if (event->button() == Qt::LeftButton)
但是您创建事件时从未设置过按钮,因此 event->button()
永远不会等于 Qt::LeftButton
。
我写了一些示例代码来帮助您开始使用这些事件:
main.cpp:
#include <QApplication>
#include "clickwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ClickWindow clickWindow;
clickWindow.show();
return a.exec();
}
clickwindow.h(我省略了头球后卫以节省一些 space):
#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DCore/QEntity>
class ClickWindow : public Qt3DExtras::Qt3DWindow {
public:
ClickWindow();
// Here we say we want to have a custom handling of click events
void mousePressEvent(QMouseEvent *eventPress) override;
private:
Qt3DCore::QEntity *createScene();
};
clickwindow.cpp:
#include "clickwindow.h"
#include <QDebug>
#include <Qt3DRender/QCamera>
#include <Qt3DRender/QMaterial>
#include <Qt3DExtras/QGoochMaterial>
#include <Qt3DExtras/QCuboidMesh>
ClickWindow::ClickWindow() : Qt3DExtras::Qt3DWindow() {
// You could also create a dedicated setup method
setRootEntity(createScene());
Qt3DRender::QCamera *camera = this->camera();
camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
camera->setPosition(QVector3D(5.0, 5.0, 5.0f));
camera->setViewCenter(QVector3D(0, 0, 0));
}
void ClickWindow::mousePressEvent(QMouseEvent *eventPress) {
// No need to pass it on to the parent! It will receive it
// anyway. You can stop event propagation by calling
// eventPress->accept();
// This is where the click is received
qDebug() << "Click!";
}
Qt3DCore::QEntity* ClickWindow::createScene() {
// Root entity
Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity;
// Material
//Qt3DRender::QMaterial *material = new Qt3DExtras::QPhongMaterial(rootEntity);
Qt3DRender::QMaterial *material = new Qt3DExtras::QGoochMaterial(rootEntity);
//Cube
Qt3DCore::QEntity *cubeEntity = new Qt3DCore::QEntity(rootEntity);
Qt3DExtras::QCuboidMesh *cubeMesh = new Qt3DExtras::QCuboidMesh;
cubeEntity->addComponent(cubeMesh);
cubeEntity->addComponent(material);
return rootEntity;
}
您还可以使用 Qt3D
classes 处理点击,并遵循此示例 here, but to me, depending on your application, this seems a bit over the top. If you simply want to receive the 2D screen coordinates I'd prefer the solution above. If you need custom inputs for e.g. clicking on an object I answered a question regarding this here or if you simply need the 3D coordinates clicked on an object you can use the QObjectPicker class。
如果您遇到任何 QML 代码,请记住 QML 代码只是实例化 C++ classes,也就是说,您可以转移示例,有时会在命名等方面做一些细微的改动。
我想在 Qt3D Window 上获取鼠标事件(如鼠标位置),每次我在 window.
中单击时我看过
我刚刚开始学习 C++ 和 Qt,所以我正在努力使最简单的程序成为可能。在下面的代码中(我所有的程序都在这段代码中),我想在Qt3DWindow中每次点击时都得到鼠标位置,但我什至无法在每次点击时得到调试消息。
据我了解,mouseMoveEvent
函数仅在程序执行时调用一次。如果 Qt 中有这样的东西,我将如何在主循环中调用这个函数?
我需要做这样的事情吗?
Qt3DInput::QMouseDevice *mouse = new Qt3DInput::QMouseDevice(scene);
但是我该如何使用它呢?
#include <QGuiApplication>
#include <Qt3DCore/QEntity>
#include <Qt3DRender/QCamera>
#include <Qt3DRender/QCameraLens>
#include <Qt3DCore/QTransform>
#include <Qt3DCore/QAspectEngine>
#include <Qt3DInput/QInputAspect>
#include <Qt3DRender/QRenderAspect>
#include <Qt3DExtras/QForwardRenderer>
#include <Qt3DExtras/QPhongMaterial>
#include <Qt3DExtras/QGoochMaterial>
#include <Qt3DExtras/QSphereMesh>
#include <Qt3DExtras/QCuboidMesh>
#include <QMouseEvent>
#include <Qt3DInput/QMouseDevice>
#include <Qt3DInput/QMouseHandler>
#include <Qt3DInput/QMouseEvent>
#include <QDebug>
#include "qt3dwindow.h"
void mouseMoveEvent(Qt3DInput::QMouseEvent *event);
Qt3DCore::QEntity *createScene()
{
// Root entity
Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity;
// Material
//Qt3DRender::QMaterial *material = new Qt3DExtras::QPhongMaterial(rootEntity);
Qt3DRender::QMaterial *material = new Qt3DExtras::QGoochMaterial(rootEntity);
//Cube
Qt3DCore::QEntity *cubeEntity = new Qt3DCore::QEntity(rootEntity);
Qt3DExtras::QCuboidMesh *cubeMesh = new Qt3DExtras::QCuboidMesh;
cubeEntity->addComponent(cubeMesh);
cubeEntity->addComponent(material);
return rootEntity;
}
int main(int argc, char* argv[])
{
QGuiApplication app(argc, argv);
Qt3DExtras::Qt3DWindow view;
Qt3DCore::QEntity *scene = createScene();
// Camera
Qt3DRender::QCamera *camera = view.camera();
camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
camera->setPosition(QVector3D(5.0, 5.0, 5.0f));
camera->setViewCenter(QVector3D(0, 0, 0));
Qt3DInput::QMouseEvent *e;
mouseMoveEvent(e);
view.setRootEntity(scene);
view.show();
return app.exec();
}
void mouseMoveEvent(Qt3DInput::QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
qDebug() << "ok";
}
}
通常 "mouseMoveEvent" 与 Qwidget 绑定。
这是Qt3DInput::QmouseEvent
的源代码:
class QT3DINPUTSHARED_EXPORT QMouseEvent : public QObject {
Q_OBJECT
private:
QT_PREPEND_NAMESPACE(QMouseEvent) m_event;
};
m_event已经包含了您鼠标的信息,应该会自动处理。
Mouse events occur when a mouse button is pressed or released inside a widget, or when the mouse cursor is moved.
所以,我认为您不需要创建新的 Qt3DInput::QMouseDevice
。你不应该这样做 Qt3DInput::QMouseEvent *e
;因为小部件会自动获取它。
我不知道如何在不在 Qwidget 中覆盖它的情况下使用 mouseEvent,Qt3DExtras::Qt3DWindow 视图应该包含默认值 mouseMoveEvent()
。
如果你只想打印一个"ok",我建议你不要写任何关于mouseMoveEvent()
的东西。如果您希望鼠标移动时发生某些事情,您应该覆盖视图的 mouseMoveEvent()
.
你在这里做错了几件事。
首先,我建议你subclass Qt3DWindow
并将场景的设置代码放在那里。这毕竟是意见责任。主体应该保持简单和干净。当然不要在视图中放置任何重要的逻辑,但设置代码应该在那里(坚持模型-视图-控制器)。
接下来,您当然不会收到任何调试消息,因为您在那里进行了检查
if (event->button() == Qt::LeftButton)
但是您创建事件时从未设置过按钮,因此 event->button()
永远不会等于 Qt::LeftButton
。
我写了一些示例代码来帮助您开始使用这些事件:
main.cpp:
#include <QApplication>
#include "clickwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ClickWindow clickWindow;
clickWindow.show();
return a.exec();
}
clickwindow.h(我省略了头球后卫以节省一些 space):
#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DCore/QEntity>
class ClickWindow : public Qt3DExtras::Qt3DWindow {
public:
ClickWindow();
// Here we say we want to have a custom handling of click events
void mousePressEvent(QMouseEvent *eventPress) override;
private:
Qt3DCore::QEntity *createScene();
};
clickwindow.cpp:
#include "clickwindow.h"
#include <QDebug>
#include <Qt3DRender/QCamera>
#include <Qt3DRender/QMaterial>
#include <Qt3DExtras/QGoochMaterial>
#include <Qt3DExtras/QCuboidMesh>
ClickWindow::ClickWindow() : Qt3DExtras::Qt3DWindow() {
// You could also create a dedicated setup method
setRootEntity(createScene());
Qt3DRender::QCamera *camera = this->camera();
camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
camera->setPosition(QVector3D(5.0, 5.0, 5.0f));
camera->setViewCenter(QVector3D(0, 0, 0));
}
void ClickWindow::mousePressEvent(QMouseEvent *eventPress) {
// No need to pass it on to the parent! It will receive it
// anyway. You can stop event propagation by calling
// eventPress->accept();
// This is where the click is received
qDebug() << "Click!";
}
Qt3DCore::QEntity* ClickWindow::createScene() {
// Root entity
Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity;
// Material
//Qt3DRender::QMaterial *material = new Qt3DExtras::QPhongMaterial(rootEntity);
Qt3DRender::QMaterial *material = new Qt3DExtras::QGoochMaterial(rootEntity);
//Cube
Qt3DCore::QEntity *cubeEntity = new Qt3DCore::QEntity(rootEntity);
Qt3DExtras::QCuboidMesh *cubeMesh = new Qt3DExtras::QCuboidMesh;
cubeEntity->addComponent(cubeMesh);
cubeEntity->addComponent(material);
return rootEntity;
}
您还可以使用 Qt3D
classes 处理点击,并遵循此示例 here, but to me, depending on your application, this seems a bit over the top. If you simply want to receive the 2D screen coordinates I'd prefer the solution above. If you need custom inputs for e.g. clicking on an object I answered a question regarding this here or if you simply need the 3D coordinates clicked on an object you can use the QObjectPicker class。
如果您遇到任何 QML 代码,请记住 QML 代码只是实例化 C++ classes,也就是说,您可以转移示例,有时会在命名等方面做一些细微的改动。