Search code examples
pythonpyqt4flags

Always on top behavior through a check box PyQt


There is a lot of information on the "always on top" issue but I'm too inexperienced to get through. I want to have a CheckBox (aboveAll) on my window (which is QDialog) to toggle window's behavior from 'normal' to 'always on top'. The closest I get:

from PyQt4.QtGui import *
class MyForm(QtGui.QDialog):
    def __init__(self, parent = None):
        QtGui.QWidget.__init__(self,parent)
        self.ui = Ui_Kamipy()
        self.ui.setupUi(self)
        self.ui.aboveAll.stateChanged.connect(self.ABOVE)
    def ABOVE(self):
        if self.ui.aboveAll.isChecked() == True:
            self.ui.setWindowFlags(self.ui.windowFlags() & ~QtCore.Qt.WindowStaysOnTopHint)
        if self.ui.aboveAll.isChecked() == False:
            self.ui.setWindowFlags(self.ui.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)

And it brings the following error:

Traceback (most recent call last): File "kamimimi.pyw", line 17, in ABOVE self.ui.setWindowFlags(self.ui.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) AttributeError: 'Ui_Kamipy' object has no attribute 'setWindowFlags'

is it because my window is a dialog (not main window)? How can I fix it?


Solution

  • Your window is a dialog. But you are not calling the methods of your window; you are calling the methods of self.ui - which, as the traceback tells you, is of type Ui_Kamipy, not QDialog.

    The self.ui object is a just a simple python wrapper class that provides a namespace for the widgets you added in Qt Designer. When you call its setupUi method, you pass in an instance of whatever is the top-level class you created in Qt Designer. So in this case, the top-level class is QDialog, and you pass in the instance self.

    So the window is self, and its child widgets can be accessed as attributes of the namespace self.ui. This means your code should look more like this:

    from PyQt4 imort QtCore, QtGui
    
    class MyForm(QtGui.QDialog):
        def __init__(self, parent=None):
            QtGui.QDialog.__init__(self, parent)
            self.ui = Ui_Kamipy()
            self.ui.setupUi(self)
            self.ui.aboveAll.stateChanged.connect(self.ABOVE)
    
        def ABOVE(self):
            if self.ui.aboveAll.isChecked():
                self.setWindowFlags(
                    self.windowFlags() & ~QtCore.Qt.WindowStaysOnTopHint)
            else:
                self.setWindowFlags(
                    self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)
            self.show()
    

    Note that I have added the line self.show() at the bottom, because setWindowFlags can cause the window to become hidden.