Qt-如何在Qt3DWindow上获取鼠标事件

时间:2018-07-19 12:26:32

标签: c++ qt qt3d

每次在窗口内部单击时,我想在Qt3D窗口上获取鼠标事件(例如鼠标位置)。

我见过this questionalso the same question on this forum),但是我的Qt3DWindow不在任何小部件内,所以我认为我不需要EventFilter。

我只是乞求学习C ++和Qt,所以我正在尝试使最简单的程序成为可能。在下面的代码中(我的所有程序都在此代码中),我想每次在Qt3D窗口中单击时都获得鼠标位置,但是每次单击时甚至都无法获得调试消息。

据我了解,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";
    }
}

2 个答案:

答案 0 :(得分:2)

您在这里做错了几件事。

首先,我建议您继承Qt3DWindow的子类,然后在此处放置场景的设置代码。毕竟那是意见的责任。主体应保持简单清洁。当然,不要在视图中放置任何重要的逻辑,但是设置代码应该在那里(坚持使用Model-View-Controller)。

接下来,您当然不会收到任何调试消息,因为您已经在此处进行了检查

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(我省略了标题保护以节省一些空间):

#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类来处理点击,并遵循此示例here,但是对我来说,根据您的应用程序,这似乎有点过头了。如果您只想接收2D屏幕坐标,则希望使用上述解决方案。如果您需要自定义输入,例如单击一个对象,我回答了有关此here的问题,或者如果您只需要单击对象上的3D坐标,则可以使用QObjectPicker类。

如果遇到任何QML代码,请记住,QML代码只是实例化C ++类,即,您可以传输示例,有时在命名上进行较小的更改等。

答案 1 :(得分:0)

通常,“ mouseMoveEvent”是与Qwidget绑定的。

这是Qt3DInput::QmouseEvent的源代码:

class QT3DINPUTSHARED_EXPORT QMouseEvent : public QObject {
    Q_OBJECT 
private:
    QT_PREPEND_NAMESPACE(QMouseEvent) m_event;  
};

m_event已包含您的鼠标信息,应该会自动对其进行处理。

  

在鼠标内部按下或释放鼠标键时会发生鼠标事件   小部件,或者当鼠标光标移动时。

因此,我认为您不需要创建新的Qt3DInput::QMouseDevice。而且你不应该做Qt3DInput::QMouseEvent *e;因为小部件会自动获取它。

我不知道如何在不将其覆盖到Qwidget中的情况下使用mouseEvent,并且Qt3DExtras :: Qt3DWindow视图应包含默认的mouseMoveEvent()。 如果您只想打印出“确定”,我建议您不要写任何关于mouseMoveEvent()的内容。如果希望在移动鼠标时发生某些情况,则应覆盖视图的mouseMoveEvent()