关闭任何模态 QDialog 后焦点不会返回到 QMainWindow,直到用鼠标单击

coo*_*nal 5 c++ qt yocto

我的 Qt5 桌面应用程序在显示主窗口后立即显示一个模式对话框。主窗口显示为带标志的全屏Qt::FramelessWindowHint。问题是当我关闭对话框时,焦点不会返回到主窗口。对于随后在应用程序中打开的任何对话框都是如此。

主窗口上的特定按钮应该具有焦点,并通过调用来设置QWidget::setFocus()。但该按钮上的焦点仍然不可见(焦点上用不同的颜色突出显示)。我还观察到QApplication::activeWindow()此时返回 NULL。仅当用鼠标单击主窗口的空白区域时才能看到焦点。这使得仅使用键盘工作变得困难。

在 Windows 和 Ubuntu 上部署都没有问题,完美运行。但是当部署在 Yocto Linux 上时,就会出现这个问题。

Yocto Linux 在没有窗口管理器和桌面环境的情况下运行。这会是窗口无法自动激活的问题吗?

p-a*_*l-o 2

在这种情况下(没有窗口管理器),我能想到的唯一解决方法是使用,例如在显示对话框grabKeyboard的插槽中:QDialog

void MainWindow::on_pushButton_clicked()
{
    /* ... */

    dialog.exec();
    grabKeyboard();
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果没有窗口管理器,就没有顶级小部件的激活Qt::FramelessWindowHint之类的东西,并且装饰标志(如)也没有任何意义。

如果这个技巧恰好满足您的需求,您可以使用如下函数:

void showModalDialog(QDialog * dialog)
{
    dialog->exec();
    dialog->parentWidget()->grabKeyboard();
}
Run Code Online (Sandbox Code Playgroud)

并在需要时使用它。

如果背景小部件不是对话框的父级,请使用重载:

void showModalDialog(QDialog * dialog, QWidget * background)
{
    dialog->exec();
    background->grabKeyboard();
}
Run Code Online (Sandbox Code Playgroud)

或者将它们全部混合在一个函数中:

void showModalDialog(QDialog * dialog, QWidget * background = nullptr)
{
    dialog->exec();
    if (background == nullptr)
    {
        background = dialog->parentWidget();
    }
    if (background != nullptr)
    {     
        background->grabKeyboard();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您担心(或经历)与其他平台发生冲突,请使用#definefor yocto 并将调用后的所有内容包装exec()在通常的 中#ifdef,例如

void showModalDialog(QDialog * dialog, QWidget * background = nullptr)
{
    dialog->exec();
#ifdef YOCTO_LINUX
    if (background == nullptr)
    {
        background = dialog->parentWidget();
    }
    if (background != nullptr)
    {
        background->grabKeyboard();
    }
#endif
}
Run Code Online (Sandbox Code Playgroud)