Unsolved Is it possible to QProgressDialog::show without bringing the dialog to the front when the application is minimized/hidden?
-
I have an application that when you press a button it launches two processes one after the other. Both take some time. So it is topical for the user to minimize the window of my app or change to another window to do something while he/she waits. The problem is that when the first process finishes and the second one starts,
QProgressDialog::show
is called and the widget is shown on top of all other windows in the os, changing the focus of whatever the user is doing in another software. I do not want that to happen. I want the progress dialog to be shown only to the parent widget/application, but if the application is not shown (i.e. it is behind some other window in the os) it should not be brought to the front.Here is an example that reproduces my problem:
#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(); }
If you compile the example, run it and click the button, and after that change to some other program, when the first process finishes my app will appear again on top.
One option would be to merge the two processes, but it is not a solution for the real application as the two processes happen in different widgets as a result of a trigger of the first process. Moreover, the second process can be done by itself as well...
Any idea on how to "show" the progress dialog to the application but not bring the application to the front automatically as a consequence of that
QProgressDialog::show
?This happens to me in Ubuntu 18.04 with Qt 5.9.5 as well as with Qt5.13.2. I have tried with Windows and Qt 5.14.2 with the desired behaviour with the code as is above. Here you can see a gift of the behavior that is not desired, first with Qt 5.13.2 and then with Qt 5.9.5:
I have also tried with the same non-desired behaviour result:
- Using
QDialog::open
instead ofQWidget::show
. - Using
QWidget::setVisible
instead ofQWidget::show
. - Adding
progress->setAttribute(Qt::WA_ShowWithoutActivating);
before callingshow()
. - Adding
progress->setWindowFlag(Qt::WindowDoesNotAcceptFocus, true);
before callingshow();
- Using
-
Hi,
Can you add the Qt version as well as the OS you are running on ?
-
@apalomer said:
Any idea on how to "show" the progress dialog to the application but not bring the application to the front automatically as a consequence of that QProgressDialog::show?
That's actually how it behaves for me on Windows. Might be your OS/Qt version thing, as @SGaist hinted at.
In any case you can try to addprogress->setAttribute(Qt::WA_ShowWithoutActivating);
before callingshow()
. -
I have tried this with Ubuntu 18.04 and Qt 5.9.5 as well as Qt 5.13.2. I've updated my original question to include this as well as a giff of what happens.
-
Did you find a solution? I have the same problem on Windows, Qt 5.9.1. I've also got the ShowWithoutActivating flag set on the QDialog.
I've tried installing a native event handler and filtering out all the WM_ACTIVATE events, but that doesn't help.
Something that might be related is that Qt seems to pop the main window to the front whenever you add a widget to something that doesn't already have a parent, so you have to be very careful about the order that things are created and added in. I'm not sure why this is, but experimentally it makes a difference in other parts of my app. -
Actually I got this case to work by using these flags.
dialog->setAttribute(Qt::WA_ShowWithoutActivating); dialog->setWindowFlags(Qt::WindowDoesNotAcceptFocus | Qt::FramelessWindowHint);