c++ - 应用程序激活时如何将焦点设置为非模态 QDialog?
问题描述
我有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);
}
听起来很简单,但我尝试了各种方法,但没有任何运气:
方法 1:监听 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);
}
解决方案
一种有效的方法是在应用程序激活时监听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()
如果有人知道请在下方评论。
推荐阅读
- python - 某些脚本在使用 subprocess.Popen() 时失败,但在 crontab 或手动运行中运行完美
- react-native - 不变违规:requirenativecomponent:在uimanager中找不到“rncamera”
- java - 如何迭代具有数组列表的数组?
- reactjs - 仅当状态为 true 时才应用 fetch 回调
- c# - MVC、Angular 8 和 signalR 随机行为,有时无法连接到集线器,如何解决?
- ruby-on-rails - 如何让 Rails 识别我添加到 usr/bin 的 sqlite3 版本?
- azure - 如何将拒绝分配置于 Azure 订阅或资源组级别?
- delphi - Delphi Rio 10.3.2 - 无法注册简单的 32 位 ActiveX 服务器
- javascript - 悬停效果等待ajax调用
- r - 是否可以删除 R 中重复的句子/文本块?