当应用程序最小化/隐藏时,是不是可以 QProgressDialog::show 而不将对话框置于前面?

Posted

技术标签:

【中文标题】当应用程序最小化/隐藏时,是不是可以 QProgressDialog::show 而不将对话框置于前面?【英文标题】:Is it possible to QProgressDialog::show without bringing the dialog to the front when the application is minimized/hidden?当应用程序最小化/隐藏时,是否可以 QProgressDialog::show 而不将对话框置于前面? 【发布时间】:2020-07-03 12:23:29 【问题描述】:

我有一个应用程序,当您按下按钮时,它会依次启动两个进程。两者都需要一些时间。因此,用户在等待时最小化我的应用程序的窗口或切换到另一个窗口来做某事是很重要的。问题是,当第一个进程完成并且第二个进程启动时,QProgressDialog::show 被调用,并且小部件显示在操作系统中所有其他窗口的顶部,从而改变了用户在另一个软件中所做的任何事情的焦点。我不希望这种情况发生。我希望仅向父窗口小部件/应用程序显示进度对话框,但如果未显示应用程序(即它位于操作系统中的某个其他窗口的后面),则不应将其带到前面。

这是一个重现我的问题的示例:

#include <QApplication>
#include <QGridLayout>
#include <QLabel>
#include <QProgressDialog>
#include <QPushButton>
#include <QTimer>

#define WAIT_TIME_MS 3000

QProgressDialog* createProgress(const QString& title, QWidget* parent = nullptr)

  QProgressDialog* progress = new QProgressDialog(title, "", 0, 0, parent);
  progress->setWindowTitle("Progress dialog");
  progress->setWindowFlag(Qt::CustomizeWindowHint, true);
  progress->setWindowFlag(Qt::WindowCloseButtonHint, false);
  progress->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
  progress->setWindowModality(Qt::WindowModal);
  progress->setCancelButton(nullptr);
  progress->show();
  return progress;


int main(int argc, char** argv)

  // Create application
  QApplication app(argc, argv);

  // Create widget
  QWidget* w = new QWidget;
  w->setLayout(new QGridLayout);
  w->setMinimumSize(QSize(800, 600));

  // Add button
  QPushButton* pb = new QPushButton("Push to compute");
  w->layout()->addWidget(pb);

  // Add label
  w->layout()->addWidget(new QLabel("Compile version: " + QString::fromUtf8(QT_VERSION_STR)));
  w->layout()->addWidget(new QLabel("Runtime version: " + QString::fromUtf8(qVersion())));

  // Connect push button click
  QObject::connect(pb, &QPushButton::clicked, pb, [w]() 
    // Create first progress dialog
    QProgressDialog* progress_1 = createProgress("First progress dialog", w);

    // After WAIT_TIME_MS milliseconds show the progress dialog
    QTimer::singleShot(WAIT_TIME_MS, [w, progress_1]() 
      // Close previous progress
      progress_1->hide();
      progress_1->deleteLater();

      // Create progress dialog
      QProgressDialog* progress_2 = createProgress("Second progress dialog", w);

      // Hide and destory progress dialog after WAIT_TIME_MS more milliseconds
      QTimer::singleShot(WAIT_TIME_MS, [progress_2]() 
        progress_2->hide();
        progress_2->deleteLater();
      );
    );
  );

  w->show();
  return app.exec();

如果您编译示例,运行它并单击按钮,然后切换到其他程序,当第一个进程完成时,我的应用程序将再次出现在顶部。

一种选择是合并这两个进程,但这不是真正的应用程序的解决方案,因为两个进程发生在不同的小部件中,这是第一个进程触发的结果。而且,第二道工序也可以自己完成……

知道如何向应用程序“显示”进度对话框,但不会因为 QProgressDialog::show 而自动将应用程序置于最前面?

这发生在我的 Ubuntu 18.04 和 Qt 5.9.5、Qt 5.13.2、Qt 5.14.2 和 Qt 5.15.0。我还尝试使用 Windows 和 Qt 5.14.2 使用上面的代码获得所需的行为。在这里,您可以看到 不想要的行为,首先是 Qt 5.13.2,然后是 Qt 5.9.5:

我也尝试过相同的非预期行为结果:

使用QDialog::open 代替QWidget::show。 使用QDialog::setVisible 代替QWidget::show。 在调用progress-&gt;show()之前添加progress-&gt;setAttribute(Qt::WA_ShowWithoutActivating);。 在调用progress-&gt;show();之前添加progress-&gt;setWindowFlag(Qt::WindowDoesNotAcceptFocus, true);

【问题讨论】:

嗨,在 windows 10 1903 和 qt 5.12.3 中,第二个进度条关注系统没有问题,它停留在 chrome 窗口后面。 我在 Linux 和 Windows 的 Qt5.10 中都没有看到这个问题。 我会下载并编译一个更新版本的Qt,看看版本是否如此。我已经使用 Qt 5.9.5 在 Linux 18.04 中进行了测试。 因为它有一个专门的打开方法,你有没有试过用它来代替show? QDialog::open 也会发生同样的事情。 【参考方案1】:

你试过这个void QWidget::showMinimized() 吗?

您可以通过处理来检查应用程序的状态 QApplication::applicationStateChanged signal

【讨论】:

以上是关于当应用程序最小化/隐藏时,是不是可以 QProgressDialog::show 而不将对话框置于前面?的主要内容,如果未能解决你的问题,请参考以下文章

隐藏阶段时的JavaFX 8内存泄漏

如何检查我的窗口是不是隐藏/可见?

c语言能不能将dos窗口隐藏,不是最小化

当试图最小化包含不同整数形状的矩形的矩形空间时,是不是可以避免回溯?

隐藏子小部件时,QGridLayout 未调整大小或重新绘制

在C#编程中如何实现把窗体的自带的关闭按钮隐藏但是最小化不隐藏