【问题标题】:How to set focus to non-modal QDialog when application becomes active?应用程序激活时如何将焦点设置为非模态 QDialog?
【发布时间】:2021-05-08 10:54:24
【问题描述】:

我有一个MainWindow 和一个非模态QDialog 和一个QPushButton,只是为了显示对话框。当应用程序再次最小化和最大化时,我希望对话框(如果可见)重新获得键盘焦点。

代码如下:

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class MainWindow : public QMainWindow
{
    Q_OBJECT
    QDialog *dialog;
public:
    explicit MainWindow(QWidget *parent = nullptr);
};

#endif // MAINWINDOW_H

主窗口.cpp

#include "mainwindow.h"
#include <QPushButton>
#include <QDialog>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    dialog(new QDialog(this))
{
    QPushButton *button = new QPushButton("show dialog", this);
    connect(button, &QPushButton::clicked, dialog, &QDialog::show);
    setCentralWidget(button);
}

听起来很简单,但我尝试了各种方法都没有运气:

方法一: 监听 QApplication::applicationStateChanged() 信号并在应用程序状态变为活动时将焦点设置为对话框。

方法 2: 监听对话框的显示和窗口激活事件并在触发时设置焦点。

方法 3: 监听主窗口的显示和窗口激活事件并在触发时设置焦点。

以下是实现上述方法的代码:

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class MainWindow : public QMainWindow
{
    Q_OBJECT
    QDialog *dialog;
public:
    explicit MainWindow(QWidget *parent = nullptr);
    virtual bool event(QEvent *event) override;
    virtual bool eventFilter(QObject *watched, QEvent *event) override;
};

#endif // MAINWINDOW_H

主窗口.cpp

#include "mainwindow.h"
#include <QPushButton>
#include <QDialog>
#include <QEvent>
#include <QApplication>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    dialog(new QDialog(this))
{
    QPushButton *button = new QPushButton("show dialog", this);
    connect(button, &QPushButton::clicked, dialog, &QDialog::show);
    setCentralWidget(button);

    dialog->installEventFilter(this);

    //set focus on dialog when app becomes active
    connect(qApp, &QApplication::applicationStateChanged, this, [this](Qt::ApplicationState state){
        if (dialog->isVisible() && state == Qt::ApplicationActive) {
            dialog->setFocus();
        }
    });
}

bool MainWindow::event(QEvent *event)
{
    //set focus on dialog when main window is shown or activated
    if (event->type() == QEvent::Show || event->type() == QEvent::WindowActivate) {
        if (dialog->isVisible()) {
            dialog->setFocus();
        }
    }

    return QMainWindow::event(event);
}

bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    //set focus on dialog when dialog is shown or activated
    if (watched == dialog) {
        if (event->type() == QEvent::Show || event->type() == QEvent::WindowActivate) {
            dialog->setFocus();
        }
    }

    return QMainWindow::eventFilter(watched, event);
}

【问题讨论】:

    标签: c++ qt focus qwidget qdialog


    【解决方案1】:

    一种有效的方法是监听QApplication::applicationStateChanged() 信号并在应用程序激活时调用QWindow::requestActivate():

    connect(qApp, &QApplication::applicationStateChanged, this, [this](Qt::ApplicationState state){
        if (dialog->isVisible() && state == Qt::ApplicationActive) {
            if (dialog->windowHandle()) dialog->windowHandle()->requestActivate();
        }
    });
    

    根据文档,不知道为什么 QWindow::requestActivate() 有效,但 QWidget::setFocus() 在两个函数都应该提供键盘焦点时不起作用。有知道的请在下方留言。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      • 2016-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多