Qt-如何在Qt3DWindow上获取鼠标事件 [英] Qt - How to get mouse events on Qt3DWindow

查看:268
本文介绍了Qt-如何在Qt3DWindow上获取鼠标事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to get mouse events (like mouse position) on a Qt3D Window, every time I click inside the window.

我已经看到这个问题(

I've seen this question (also the same question on this forum) but my Qt3DWindow is not inside any widget, so I don't think I need an EventFilter.

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

I'm just beggining to learn C++ and Qt, so I'm trying to make the simplest program possible. In the code below (all my program is in this code), I would like to get the mouse position every time I click inside the Qt3D Window, but I can't even get a debug message every time I click.

据我了解,mouseMoveEvent函数仅在程序执行时被调用一次.如果Qt中有这样的事情,我该如何在主循环中调用此函数?

As far as I understand, the mouseMoveEvent function is only called one time, when the program gets executed. How would I call this function in the main loop, if there is such a thing in Qt?

我需要做这样的事情吗?

Do I need to do something like this?

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";
    }
}

推荐答案

您在这里做错了几件事.

You're doing a couple of things wrong here.

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

First of all, I would advise you to subclass Qt3DWindow and put the setup code for the scene there. That's the views responsibility after all. The main should stay simple and clean. Of course don't put any important logic in the view, but the setup code should be there (stick to Model-View-Controller).

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

Next, of course you're not getting any debug message, because you have this check in there

if (event->button() == Qt::LeftButton)

,但是您无需设置按钮即可创建事件,因此event->button()永远不会等于Qt::LeftButton.

but you create the event without ever setting the button, so event->button() will never be equal to Qt::LeftButton.

我编写了一些示例代码来帮助您开始使用这些事件:

I wrote some example code to get you started with the events:

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

clickwindow.h (I left out the header guards to save some 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:

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类处理点击,并遵循以下示例在这里回答了一个问题,或者如果您只需要单击对象上的3D坐标,您可以使用 QObjectPicker 类.

You could also handle clicks using the Qt3D classes and follow this example 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 ++类,即,您可以传输示例,有时在名称上进行较小的更改等.

If you encounter any QML code remember that QML code simply instantiates C++ classes, i.e. you can transfer the examples, sometimes with small minor changes in naming, etc.

这篇关于Qt-如何在Qt3DWindow上获取鼠标事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆