为啥 GUI 卡住并且后台进程运行良好?

Posted

技术标签:

【中文标题】为啥 GUI 卡住并且后台进程运行良好?【英文标题】:Why GUI is getting stucked and background process is running perfectly?为什么 GUI 卡住并且后台进程运行良好? 【发布时间】:2020-12-16 18:55:48 【问题描述】:

我这样写一个程序:

cap = cv2.VideoCapture(video_path)
counter = 1
while True:
    ret, frame = cap.read()
    if not ret: break
    cv2.imwrite(...)
    self.progressbar.setValue(int((counter / self.totalFrame)*100))
    time.sleep(1)
    counter += 1

self.progressbar.setValue(0)
cap.release()

我想使用 opencv 从视频中提取所有帧,并希望在 PyQt5 进度条中显示进度。我还使用 sleep 来避免 Not Responding。但是程序显示我没有响应,进度条也被后台卡住了。工作做得很好。

如何正确显示进度条?

self.totalFrame 是视频的帧数。

进度条在 5 或 6 % 的进度后卡住 但是所有帧都被成功提取

【问题讨论】:

请提供minimal reproducible example @S.Nick 我已经发布了两个 ss。现在理解够了吗? 您正在使用 while 循环这一事实是导致 UI 无响应的主要原因,因为主 UI 线程中不应发生 阻塞time.sleep() 也是如此,它的作用与您的想法完全相反:它阻止 UI 更新和响应。如果您需要一个连续处理某些内容的 parallel 函数,则需要为此使用一个单独的“worker” QThread,并带有一个为进度条发出值的自定义信号。做一些研究,因为即使在 *** 上也有很多关于这个主题的帖子。 @musicamante 好的!非常感谢! 不确定 PyQt 但在 C++ 中有一个函数可以从这样的循环中临时返回事件循环,以便执行/更新 gui 函数 【参考方案1】:

尝试将 time.sleep(1) 替换为 cv2.waitKey(1)

【讨论】:

但是另一个问题,在 cv2.waitKey(1) 之后,进度条有响应,但是当我尝试移动 GUI 时,它会在 1/2 秒后移动。【参考方案2】:

今天我知道了如何在不实现 QThread 的情况下正确运行进度条。

我必须在声明后添加QApplication.processEvents()

cap = cv2.VideoCapture(video_path)
counter = 1
while True:
    ret, frame = cap.read()
    if not ret: break
    cv2.imwrite(...)
    self.progressbar.setValue(int((counter / self.totalFrame)*100))
    QApplication.processEvents()
    counter += 1

self.progressbar.setValue(0)
cap.release()

【讨论】:

以上是关于为啥 GUI 卡住并且后台进程运行良好?的主要内容,如果未能解决你的问题,请参考以下文章

Python Kivy:正确启动更新 GUI 元素的后台进程

如何将 Node.js 作为后台进程运行并且永不死亡?

子python进程卡住了

在pyqt5中退出GUI时终止正在运行的进程的正确方法是什么?

KETTLE后台进程执行配置方式

守护进程