【问题标题】:Why does the Qt3D QObjectPicker not work on Android if the Qt3DWindow is embedded inside a QWidget?如果 Qt3DWindow 嵌入在 QWidget 中,为什么 Qt3D QObjectPicker 在 Android 上不起作用?
【发布时间】:2019-09-04 10:11:03
【问题描述】:

我有一个 Qt 应用程序,其中包含一个 Qt3DWindow 以及多个 QWidget。要同时使用两者,Qt3DWindow 是通过 QMainWindow::createWindowContainer() 嵌入的,它在 Windows 和 Android 上都可以正常工作。对于附加到 QEntity 的 QObjectPicker 而言,情况并非如此,QObjectPicker::clicked 事件仅在 Windows 上引发,而不在 Android 上引发。但是,如果我从 QMainWindow 中删除 Qt3DWindow 并再次“独立”使用它,QObjectPicker 在两个平台上都可以正常工作。

我已经使用不同的 Qt 版本(5.10、5.12、5.13 beta)和不同的工具链(带有 GCC 的 NDK R14、带有 Clang 的 NDK R19)测试了这个用例,但没有成功。在极少数情况下,我会收到 QObjectPicker::clicked() 事件,但触摸事件远离对象的屏幕位置。

要重现该问题,最好将其扩展到“Qt 3D:简单 C++ 示例”。 将以下包含添加到 main.cpp:

#include <Qt3DRender/QObjectPicker>
#include <Qt3DRender/QPickEvent>
#include <QObject>
#include <QtWidgets/QApplication>
#include <QGuiApplication>
#include <QtWidgets/QMainWindow>

在 main.cpp/createScene() 末尾的 return 语句之前添加以下代码:

    Qt3DRender::QObjectPicker* picker = new Qt3DRender::QObjectPicker();
    QObject::connect(picker, &Qt3DRender::QObjectPicker::clicked, material, [material](Qt3DRender::QPickEvent *pickEvent){
                qDebug() << "Sphere  clicked";
                static_cast<Qt3DExtras::QPhongMaterial*>(material)->setAmbient(QColor(rand()%255,rand()%255,rand()%255));
            });
    sphereEntity->addComponent(picker);

要为 Android 编译和部署,请创建一个 AndroidManifest.xml 并从“android:configChanges”中删除“密度”标志。 正在运行的应用程序应显示环面和移动的球体,当触摸球体时,两者的颜色会随机变化。

接下来将 main.cpp/main() 中的 QGuiApplication app(argc, argv); 替换为 QApplication app(argc, argv); 并在 return 语句之前附加以下代码:

    QMainWindow* mainWindow = new QMainWindow();
    mainWindow->resize(800, 600);
    auto centralwidget = new QWidget(mainWindow);
    mainWindow->setCentralWidget(centralwidget);
    auto container = QMainWindow::createWindowContainer(&view,mainWindow->centralWidget());
    mainWindow->show();
    container->resize(mainWindow->centralWidget()->size());

现在 Android 应用在小部件中显示相同的场景,但触摸球体不会改变颜色。 (在 Windows 上则相反)

注释掉最后三行会使示例再次运行:

    //auto container = QMainWindow::createWindowContainer(&view,mainWindow->centralWidget());
    //mainWindow->show();
    //container->resize(mainWindow->centralWidget()->size());

您知道这是配置错误还是错误?

【问题讨论】:

    标签: android c++ qt qt3d qtwidgets


    【解决方案1】:

    感谢 user3405291 的提示,我终于通过将事件过滤器附加到由 QMainWindow::createWindowContainer 返回的容器小部件,过滤掉 QEvent::MouseButtonRelease,调用 QScreenRayCaster::trigger 并将事件位置作为参数并接收到通过QScreenRayCaster::hitsChanged 拾取对象。 在 Windows 上,此过程也有效,但前提是事件过滤器附加到 Qt3DWindow 本身,而不是容器小部件。 我的假设是,在 Windows 上,鼠标事件从容器小部件转发到 Qt3DWindow,而在 Android 上,它们由容器小部件使用。由于QObjectPicker 似乎(仅)监听Qt3DWindow 上的事件,它在Android 上无法正常工作,并且无法手动将事件转发给它。 但这只是一个肤浅的印象,我很乐意进一步澄清。

    【讨论】:

      【解决方案2】:

      对象选择器仅适用于鼠标单击。如果你需要触摸手势,你需要使用QScreenRayCaster 解释here

      【讨论】:

      • QScreenRayCaster 是一个有用的提示,因为它更具适应性。不过不是事件类型的问题,似乎更多的是事件路由的问题(不同平台的路由不同)
      猜你喜欢
      • 1970-01-01
      • 2018-04-16
      • 1970-01-01
      • 2021-02-10
      • 2021-02-21
      • 1970-01-01
      • 2011-01-14
      • 1970-01-01
      • 2021-02-11
      相关资源
      最近更新 更多