簡體   English   中英

Qt-如何在Qt3DWindow上獲取鼠標事件

[英]Qt - How to get mouse events on Qt3DWindow

每次我在窗口內單擊時,我都希望在Qt3D窗口上獲得鼠標事件(如鼠標位置)。

我已經看到了這個問題在該論壇上也 遇到 了同樣的問題 ),但是我的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";
    }
}

您在這里做錯了幾件事。

首先,我建議您將Qt3DWindow子類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類處理點擊,並在此處遵循此示例,但對我而言,根據您的應用程序,這似乎有點過頭。 如果您只想接收2D屏幕坐標,則希望使用上述解決方案。 如果您需要自定義輸入,例如單擊對象,我在這里回答了有關此問題,或者您只需要單擊對象的3D坐標,則可以使用QObjectPicker類。

如果遇到任何QML代碼,請記住,QML代碼只是將C ++類實例化,即,您可以傳輸示例,有時在命名上進行較小的更改等。

通常,“ 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 ; 因為小部件將自動獲取它。

我不知道如何使用mouseEvent而不在Qwidget中覆蓋它,並且Qt3DExtras :: Qt3DWindow視圖應該包含默認的mouseMoveEvent() 如果您只想打印一個“確定”,建議您不要寫任何有關mouseMoveEvent() 如果希望在移動鼠標時發生某些情況,則應重寫視圖的mouseMoveEvent()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM