Search code examples
macospyqt5pyside2qpushbuttonqtimer

What is causing this weird UI behavior in simple QTimer example with pygt5 or pyside2 under MacOs?


I'm new to PyQt5. I copied a simple QTimer example off the internet. It worked kind of, but I get weird artifacts and the button disable/enable functionality doesn't work properly. I tried a number of simple changes but the problem persists. I don't know if the is a basic lack of understanding of the exectutuion model, or a bug in PyQt5. I get exactly the same weird effects using PySide2. Here's the code:

import sys
from PySide2.QtWidgets import *
# from PyQt5.QtWidgets import *
from PySide2.QtCore import QTimer,QDateTime
# from PyQt5.QtCore import QTimer,QDateTime

class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('QTimer example')

        self.listFile=QListWidget()
        self.label=QLabel('Label')
        self.startBtn=QPushButton('Start')
        self.endBtn=QPushButton('Stop')

        widget = QWidget()
        vlayout = QVBoxLayout()
        hlayout = QHBoxLayout()

        self.running = False
        self.endBtn.setEnabled(False)
        self.timer=QTimer()
        self.timer.timeout.connect(self.showTime)

        hlayout.addWidget(self.startBtn)
        hlayout.addWidget(self.endBtn)
        vlayout.addWidget(self.label)
        vlayout.addLayout(hlayout)

        self.startBtn.clicked.connect(self.start_timer)
        self.endBtn.clicked.connect(self.endTimer)

        widget.setLayout(vlayout)
        self.setCentralWidget(widget)

    def showTime(self):
        time=QDateTime.currentDateTime()
        timeDisplay=time.toString('yyyy-MM-dd hh:mm:ss dddd')
        self.label.setText(timeDisplay)


    def start_timer(self):
        self.startBtn.setEnabled(False)
        self.endBtn.setEnabled(True)
        self.timer.start(1000)

    def endTimer(self):
        self.startBtn.setEnabled(True)
        self.endBtn.setEnabled(False)
        self.timer.stop()

if __name__ == '__main__':
    app=QApplication(sys.argv)
    form=Window()
    form.show()
    sys.exit(app.exec_())

I saw some posts in the internet about similar issues limited to MacOS and talking about downgrading PyQt5, which is one of the reasons I tried PySide2

In addition to the button disable functionality not working completely, I see the following visual artifact:

enter image description here

Here are the relevant versions:

Mac OS Catalina, Python 3.7, pyqt5 5.12.3, pyside2 5.13.2


Solution

  • It turns out that this is another example of a Mac specific bug in PyQt5, as mentioned here:

    PyQt widget refresh behavior different when clicking button with mouse or keyboard

    Adding repaint calls into the code fixes the problem.

    It's worrisome that this obvious a bug hasn't been fixed, it makes me wonder about pyq5 on MacOS ....