首页 > 解决方案 > 需要 Qt3DWindow 来忽略键盘事件

问题描述

我有一个程序在主窗口中接受键盘输入并用它做一些事情,所以它已经在那里处理了。作为上下文:主窗口在一堆输入显示旁边有一个 Qt3DWindow 小部件,当按下键盘按钮时,这些小部件会发生变化。

该程序按预期工作,并且 keyEvents 正在主窗口中处理,直到用户与 Qt3DWindow 交互并用鼠标移动它(我在那里有一个 OrbitCameraController,所以你可以环顾四周)。一旦发生这种情况,窗口似乎会带上 MouseEvents 和 KeyEvents。因此,如果在单击 Qt3DWindow 后按下某个键,则 mainwindow 不会检测到该事件并且什么也不做。如果您只是在 Qt3DWindow 小部件之外单击,一切都会恢复正常

TLDR:

的期望:我希望即使用户使用鼠标与 Qt3DWindow 交互并环顾四周,他们仍然可以使用键盘并且输入显示仍然可以在 Qt3DWindow 小部件之外工作。

会发生什么: KeyEvent 不再传递到主窗口,并且输入显示在再次单击主窗口之前不起作用。

我尝试过的: 这是 for 上下文的代码,因为这是制作最终小部件的地方,然后将其添加到应用程序的布局中。图我在添加之前在此处修改了小部件,因此它不需要 keyEvents。

//More view and scene configuration above...
view->setRootEntity(scene);
view->defaultFrameGraph()->setClearColor(QColor(QRgb(0x05050f)));

//Create the widget based off the Qt3DWindow
QWidget *container = QWidget::createWindowContainer(view);
//Add widget to layout in mainwindow
ui->simulation_Frame->layout()->addWidget(container);

我已经尝试修改容器,使其具有 NoFocus 策略——我认为可能只是 Qt3DWindow 小部件正在获取焦点,并且将焦点策略设置为 NoFocus 至少会使其无法与之交互。尝试1:

QWidget *container = QWidget::createWindowContainer(view);
container->setFocusPolicy(Qt::NoFocus);
ui->simulation_Frame->layout()->addWidget(container);

我尝试修改容器,使其具有 setEnabled(false) - 我知道这会禁用所有输入,但我只是想看看我是否可以修改容器。尝试2:

QWidget *container = QWidget::createWindowContainer(view);
container->setEnabled(false);
ui->simulation_Frame->layout()->addWidget(container);

看来我无法修改小部件!无论我做什么,小部件仍然能够与之交互并且没有任何变化。好像我正在修改错误的小部件或其他东西。如果有人需要更多信息,我可以提供,这是一个大项目的一部分,但代码 atm 甚至都没有接近 Qt3DWindow,因为稍后我将重构 Qt3D 并将其移动到它自己的类中。

更新:

为了帮助清除一些信息,我将 KeyEvents 处理为 MainWindow 的覆盖函数(如果我理解它是如何正确调用的),如下所示:

主窗口.h

protected:
    void keyPressEvent(QKeyEvent* event);
    void keyReleaseEvent(QKeyEvent* event);

主窗口.cpp

void MainWindow::keyPressEvent(QKeyEvent *event) {
    //Only process keyPressEvents that are not repeating. (ie. Inital press)
    if (event->isAutoRepeat() == false)
    {
        switch(event->key())
        {
        case Qt::Key_W:
            // emit a signal when button has changed, which is tied to other 
            // classes slots for updating input displays
            emit keyboard_WChanged(true);
            qDebug() << "Keyboard W" << true;
            break;
        case Qt::Key_S:
            emit keyboard_SChanged(true);
            qDebug() << "Keyboard S" << true;
            break;
        //etc... more cases for each key
        }
    }
}

void MainWindow::keyReleaseEvent(QKeyEvent *event) {
    // This may not be needed for release event but never removed it lol! 
    // Still works though.
    if (event->isAutoRepeat() == false)
    {
        switch(event->key())
        {
        case Qt::Key_W:
            // emit a signal when button has changed, which is tied to other 
            // classes slots for updating input displays
            emit keyboard_WChanged(false);
            qDebug() << "Keyboard W" << false;
            break;
        case Qt::Key_S:
            emit keyboard_SChanged(false);
            qDebug() << "Keyboard S" << false;
            break;
        //etc... more cases for each key
        }
    }
}

如果这是处理键盘输入的错误方式,请告诉我!

标签: c++qtqt3d

解决方案


我决定使用Florian BlumeQt3D 小部件实现,因为它似乎解决了我遇到的所有问题。我强烈推荐使用它,因为它在设置 Qt 3D 窗口时简化了很多繁重的工作,而且真的很有帮助!不过,我宁愿将 Florian Blume 对此的评论标记为答案。因为他比我更值得享有声誉!


推荐阅读