2

I am trying to keep window by a Pin button. Here is the code:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QPushButton
from PyQt5 import QtCore

class App(QWidget):

    def __init__(self):
        super().__init__()
        self.title = 'Keep Going'
        self.width = 480
        self.height = 360
        self.initUI()


    def initUI(self):
        self.setWindowTitle(self.title)
        self.setFixedSize(self.width, self.height)
        self.layout = QVBoxLayout()
        self.button = QPushButton('PinTop')
        self.button.setCheckable(True)
        self.button.clicked.connect(self.winPinTop)
        self.layout.addWidget(self.button)
        # add tabs to widget
        self.setLayout(self.layout)
        self.show()


    def winPinTop(self):
        print('Pin')
        button = self.sender()
        if button.isChecked():
            print('on top')
            self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
            self.show()
        else:
            print('no top')
            self.setWindowFlags(self.windowFlags())
            self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

The window can not keep on top after clicking the button. I don't know how to fix this.

Infomation may help:

  • Python 3.6.8
  • PyQt version: 5.13.0
  • Ubuntu 19.04

UPDATE
I replace QWidget with QMainWindow class to check this bug.

import sys
from PyQt5.QtWidgets import QMainWindow,QApplication, QWidget, QVBoxLayout, QPushButton, QPushButton
from PyQt5 import QtCore

class App(QMainWindow):

    def __init__(self):
        super().__init__()
        self.title = 'Keep Going'
        self.width = 480
        self.height = 360
        self.initUI()


    def initUI(self):
        self.setWindowTitle(self.title)
        win = QWidget()        
        win.setFixedSize(self.width, self.height)
        layout = QVBoxLayout()
        button = QPushButton('PinTop')
        button.setCheckable(True)
        button.clicked.connect(self.winPinTop)
        layout.addWidget(button)
        # add tabs to widget
        win.setLayout(layout)
        self.setCentralWidget(win)
        self.show()


    def winPinTop(self):
        print('Pin')
        button = self.sender()
        if button.isChecked():
            print('on top')
            self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.Dialog )
            print(self.windowFlags())
            self.show()
        else:
            print('no top')
            self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.WindowStaysOnTopHint )
            print(self.windowFlags())
            self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

The problem is still here.

UPDATE 2019-9-11
After remove the show function. I can get the window on top.

def winPinTop(self):
    print('Pin')
    button = self.sender()
    if button.isChecked():
        print('on top')
        self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.Dialog )
        print(self.windowFlags())
        #self.show()
    else:
        print('no top')
        self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.WindowStaysOnTopHint )
        print(self.windowFlags())
        #self.show()

But the window will close after I click the pin button. When I show this window, it stays on the top.
I don't know why this happened.

Reference: PyQt: Always on top

l0o0
  • 773
  • 1
  • 9
  • 26
  • 1
    I cannot reproduce the problem on windows, seems to be related to Ubuntu – olinox14 Aug 30 '19 at 09:50
  • Maybe those links could help: https://stackoverflow.com/questions/30339880/setwindowflagqtdialog-qtwindowstaysontophint-not-working-on-centos , https://stackoverflow.com/questions/53141178/pyqt5-cant-delete-flag-windowstaysontophint-under-ubuntu-18-04 – olinox14 Aug 30 '19 at 09:51
  • 1
    @olinox14 thank you for your comment. I have tried `Qt.Dialog` and `Qt.X11BypassWindowManagerHint`. The window is on the top, but lost the window title. According to your comment, this is a [bug](https://bugreports.qt.io/browse/QTBUG-69515) – l0o0 Aug 30 '19 at 10:22
  • Is this your main window? Have you tried with QMainWindow? – olinox14 Aug 30 '19 at 10:23
  • @olinox14 I have added a new code for QMainWindow in my post. The problem is still here. – l0o0 Aug 30 '19 at 11:05
  • Keep in mind that its a "Hint" not an absolute to get an absolute you would have to determine how the OS handles keeping a Window always on top and utilizing that methodology within your code (if possible) for instance I am sure how you would do it in Windows 10 is totally different than how you would do it in Ubuntu – Dennis Jensen Aug 30 '19 at 14:47
  • @l0o0 Works for me on arch linux with openbox (using qt 5.13.0 and pyqt 5.13.0). Looks like an issue with whatever window manager you are using. The [window-flags docs](https://doc.qt.io/qt-5/qt.html#WindowType-enum) state that some window managers on x11 require the `X11BypassWindowManagerHint` - but with the proviso that it will result in an unmanaged. borderless window. It looks like you've already confirmed that - so the solution is to either use a different window manager, or somehow "fix" your current one. – ekhumoro Aug 30 '19 at 19:23
  • PS: The [EWMH docs](https://standards.freedesktop.org/wm-spec/wm-spec-latest.html) state that "_NET_WM_STATE_ABOVE and _NET_WM_STATE_BELOW are mainly meant for user preferences and should not be used by applications". So, strictly speaking, your window manager isn't necessarily broken if it ignores requests to set these flags. This suggests a work-around might be to use e.g. [python-xlib](https://github.com/python-xlib/python-xlib) to explicitly enforce the flags at a lower level. – ekhumoro Aug 30 '19 at 19:39

0 Answers0