QStatusBar.showMessage()更新不一致

时间:2019-08-13 22:34:19

标签: python-3.x pyqt pyqt5 sleep qstatusbar

我的道歉:

这似乎是以下情况的重复: PyQt - running a loop inside GUI

具有良好的解决方案和教程链接。

我的设置:

操作系统:Windows 10 ver1903

Python:3.7.4

PyQt5:5.13.0

我的问题:

PyQt5没有持续更新statusBar。 我在较大的应用程序中看到此问题。 我编写了此调试应用程序,以尝试更清楚地确定问题所在,并且再现了该问题:

import sys, time
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class statusdemo(QMainWindow):
   def __init__(self, parent = None):
      super(statusdemo, self).__init__(parent)

      qpb = QPushButton("Debug")
      qpb.clicked.connect(self.debug)
      self.setCentralWidget(qpb)

      self.statusBar = QStatusBar()
      self.setWindowTitle("QStatusBar Debug")
      self.setStatusBar(self.statusBar)

   def wait(self, duration=2.0):
      print(f"waiting for {duration}")
      tstart = time.time()
      while(True):
         if duration < (time.time() - tstart):
            break

   def debug(self):
      # self.statusBar.showMessage("Checkpoint 001", 2000)
      self.statusBar.showMessage("Checkpoint 001")
      # time.sleep(2)
      self.wait()
      # self.statusBar.showMessage("Checkpoint 002", 2000)
      self.statusBar.showMessage("Checkpoint 002")
      # time.sleep(2)
      self.wait()
      # self.statusBar.showMessage("Checkpoint 003", 2000)
      self.statusBar.showMessage("Checkpoint 003")
      # time.sleep(2)
      self.wait()
      # self.statusBar.showMessage("Completed debug()", 2000)
      self.statusBar.showMessage("Completed debug()")


def main():
   app = QApplication(sys.argv)
   ex = statusdemo()
   ex.show()
   sys.exit(app.exec_())


if __name__ == '__main__':
   main()

已执行:单击“调试”按钮,并定期在状态栏中打印"Checkpoint ###" 2秒钟,最后以不确定的状态栏显示“ Completed debug()”。 / p>

实际:单击“调试”按钮,以cmd格式查看wait()中的打印语句,但是直到"Checkpoint ###"为止,我都没有看到"Completed debug()"个更新

  • 我尝试过使用内置持续时间参数statusBar.showMessage()天真地使用。
  • 我尝试使用time.sleep(2)。
  • 我尝试创建自己的等待方法,该方法不应像睡眠一样挂起进程(以防万一)。

我现在似乎下一步就是尝试利用“ statusBar.messageChanged”信号,但是对于应该内置的东西来说感觉太高了。我想我丢失了显而易见但看不到的东西。

2 个答案:

答案 0 :(得分:1)

您的示例不起作用,因为wait函数中的while循环将阻止gui并阻止状态栏更新。有几种解决此问题的方法。如果状态栏更新以固定的间隔发生,则可以使用timer并将插槽连接到其timeout signal。但是,如果该插槽进行了一些繁重的计算,这仍然可能会阻塞gui-在这种情况下,您应该将计算移到工作线程中,并通过信号将更新发送回主线程(请参见here一个简单的例子)。再说一次,如果您只需要一种快速且肮脏的调试方法,则可以使用process-events临时强制gui更新。例如,您示例中的wait函数可以这样工作:

   def wait(self, duration=2.0):
      qApp.processEvents() # clear current event queue
      time.sleep(duration) # this will block gui updates

答案 1 :(得分:0)

尝试一下:

import sys, time
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class statusdemo(QMainWindow):
    def __init__(self, parent = None):
        super(statusdemo, self).__init__(parent)

        self.msgs = ["Checkpoint 001", "Checkpoint 002", "Checkpoint 003", "Completed debug()"] # +
        self.n = len(self.msgs)                                                                 # +
        self.i = 0                                                                              # +

        qpb = QPushButton("Debug")
        qpb.clicked.connect(self.debug)
        self.setCentralWidget(qpb)

        self.statusBar = QStatusBar()
        self.setWindowTitle("QStatusBar Debug")
        self.setStatusBar(self.statusBar)

        self.timer = QTimer(self)                                                               # +
        self.timer.setInterval(2000)                             
        self.timer.timeout.connect(self.show_message)

    def show_message(self):
        self.statusBar.showMessage(self.msgs[self.i])
        self.i += 1
        if self.i == self.n: 
            self.timer.stop()
            self.i = 0

    def debug(self):
        self.timer.start()


def main():
    app = QApplication(sys.argv)
    ex = statusdemo()
    ex.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

enter image description here