0

Can I force a child widget to stays on top when created inside my main window init function?

Its only working for me when the widget is created in app scope (as here PyQt4 How keep a QWidget always on top?).

(Tested on Raspberry Pi OS)

from PyQt5 import QtCore
from PyQt5.QtWidgets import (
    QApplication, QMainWindow, QWidget
)

class Ui_MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.setWindowTitle("MainWindow")
        self.resize(400, 300)
        Widget = Ui_Widget(self)
        Widget.show()

class Ui_Widget(QWidget):
    def __init__(self,  parent=None):
        QWidget.__init__(self, parent)
        self.setWindowFlags(self.windowFlags() | QtCore.Qt.Dialog)
        self.setWindowTitle("Widget")
        self.resize(400, 300)
        self.move(200, 150)

if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    MainWindow = Ui_MainWindow()
    MainWindow.show()
    # Widget = Ui_Widget(MainWindow)
    # Widget.show()

    sys.exit(app.exec_())
ramiwi
  • 902
  • 2
  • 10
  • 28
  • Do you mean that with the above code the `Ui_Widget` is shown *under* the main window? What OS are you using? – musicamante Oct 22 '21 at 19:39
  • @musicamante yes, under the main windows on Raspberry Pi OS. Just tested on windows 10 where it works fine. – ramiwi Oct 22 '21 at 20:12
  • 1
    it could be a problem with the window manager. If you click on the child window and try to click on the main window again, does it gets on top again? Try adding `self.show()` *before* creating the `Ui_Widget` instance. – musicamante Oct 22 '21 at 20:19
  • @musicamante your trick fixed it! thanks! – ramiwi Oct 22 '21 at 20:32

1 Answers1

1

The problem is probably related to some bug or wrong implementation in the window manager (on Fluxbox it works as expected).

In any case, for consistency, you should not show a child widget before showing the parent (assuming that both have to appear at the same time): MainWindow.show() is called after the __init__ is processed, and the result is that you're showing the child widget too early.

A basic workaround would be to call self.show() before showing the child widget, but it's usually considered good practice to not show widgets (including the instance itself) within the __init__.

A better solution would be to create a function that actually shows the parent widget and then creates and shows the child:

class Ui_MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.setWindowTitle("MainWindow")
        self.resize(400, 300)

    def start(self):
        self.show()
        Widget = Ui_Widget(self)
        Widget.show()

# ...

if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    MainWindow = Ui_MainWindow()
    MainWindow.start()

    sys.exit(app.exec_())

Note that using the Dialog flag for standard QWidgets is usually necessary for very specific situations. Most of the time, you could just use a QDialog and call open() instead of show(). You should also create a persistent reference for the child widget, as you might need to access it from the main window class.
Also note that classes named Ui_xyz are normally used for basic UI forms (those created with pyuic/pyside-uic), and variables should not have capitalized names, as only classes and constants use this convention (prefer mainWindow instead of MainWindow).

musicamante
  • 41,230
  • 6
  • 33
  • 58