11
votes

I have an application with several windows. Each window is a QWidget without parent.

I want those QWidget to be on top of the application, but not on top of other application. It's like the windows in Visual Studio, for instance, when they are free. They can't be hidden by the main window, but can be by an other application.

I tried with "setWindowFlags(Qt::WindowStaysOnTopHint);" , but it keeps the QWidget on top of all the applications.

3
I don't have qt installed at the moment, so I can't help a lot, but have you tried Qt::Tool as flag?Jepessen
I tried, it doesn't work. In Qt doc, it's written "If there is a parent, the tool window will always be kept on top of it. If there isn't a parent, you may consider using Qt::WindowStaysOnTopHint as well". And mine haven't parent.Nagawica
and is there a reason for having no parents, considering that they are widgets of a main application?Jepessen
Yes, they can be outside the main window.Nagawica

3 Answers

6
votes

Use SetWindowModality instead of WindowStayOnTopHint, and both modal modes (Qt::WindowModal and Qt::ApplicationModal) permit other applications to be on top of your modal window.

LE: You can read more about the difference between ApplicationModal and WindowModal in the QDialog's documentation page, here

LE 2: The problem is that you don't set a parent, so to solve this set a parent for every child window (everything except your main window) and everything will work as you expected (the child windows will be on top of the parent, but won't be on top of any other application windows):

int main(int argc, char** argv)
{
    QApplication a(argc, argv);

    QWidget w;
    QVBoxLayout* layout = new QVBoxLayout(&w);
    QPushButton* btn = new QPushButton("Show a non-modal window");
    layout->addWidget(btn);
    QWidget* mainWindow = &w;
    QObject::connect(btn, &QPushButton::clicked, [mainWindow]()
        {
            QWidget* dlg = new QWidget(mainWindow);
            QVBoxLayout* dlgLayout = new QVBoxLayout(dlg);
            dlg->setWindowFlags(Qt::Window);
            QLabel* lbl = new QLabel("Non-modal window...", dlg);
            dlgLayout->addWidget(lbl);

            dlg->show();
        });
    w.show();
    return a.exec();
}
0
votes

I've used and worked for Qt 5.3.0

setWindowFlags(Qt::FramelessWindowHint|Qt::NoDropShadowWindowHint| Qt::Window);

Qt::Tool can also be used instead of QWindow
Also set Parent before calling this. and it will work nicely

0
votes

Here's what worked for me:

I have a non-modal QDialog that I want to stay in front of my app, but only my app. Before showing the dialog I set the application's QMainWindow as its parent:

foreach( QWidget* p_widget, qApp->topLevelWidgets() )
{
    if ( QMainWindow* p_main_window = qobject_cast<QMainWindow*>( p_widget ) )
    {
        m_p_settings_dialog->setParent( p_main_window );
    }
}

Then I set the flags:

m_p_settings_dialog->setWindowFlags( Qt::Window
                                     | Qt::CustomizeWindowHint
                                     | Qt::WindowTitleHint
                                     | Qt::WindowCloseButtonHint );

And then I show the dialog.

Now it works flawlessly for me. No need to set Qt::WindowStaysOnTopFlag at all. Good luck!