PyQt5 窗口运行几秒钟后自动关闭 - “进程已完成,退出代码 -1073741819 (0xC0000005)”

问题描述 投票:0回答:2

我正在尝试使用 PyQt5 制作一个利用网络摄像头的桌面应用程序。我在 YouTube 上看到了一个视频,其中那个人使用线程来实现这一点。我根据我的用例修改了代码。修改后的代码如下:-

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import cv2


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Ayyo")

        self.GL = QGridLayout()

        self.feedLabel = QLabel()
        self.GL.addWidget(self.feedLabel, 0, 0, 1, 2)

        self.lineEdit = QLineEdit()
        self.GL.addWidget(self.lineEdit, 1, 0, 1, 1)

        self.button1 = QPushButton("Confirm")
        self.button1.clicked.connect(self.confirm)
        self.GL.addWidget(self.button1, 1, 1, 1, 1)

        self.textEdit = QTextEdit()
        self.GL.addWidget(self.textEdit, 2, 0, 2, 1)

        self.button2 = QPushButton("Clear")
        self.button2.clicked.connect(self.clear)
        self.GL.addWidget(self.button2, 2, 1, 1, 1)

        self.button3 = QPushButton("Copy")
        self.GL.addWidget(self.button3, 3, 1, 1, 1)

        self.webcam = Webcam()
        self.webcam.start()
        self.webcam.ImageUpdate.connect(self.ImageUpdateSlot)

        self.setLayout(self.GL)

        self.show()

    def ImageUpdateSlot(self, image):
        self.feedLabel.setPixmap(QPixmap.fromImage(image))

    def confirm(self):
        current = self.textEdit.toPlainText()
        self.textEdit.setPlainText(current + self.lineEdit.text())

    def clear(self):
        self.textEdit.setPlainText("")


class Webcam(QThread):
    ImageUpdate = pyqtSignal(QImage)
    
    def run(self):
        self.ThreadActive = True
        vid = cv2.VideoCapture(0)

        while True:
            ret, frame = vid.read()
            frame1 = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            image = QImage(frame1, frame1.shape[1], frame1.shape[0], frame1.strides[0], QImage.Format_RGB888)
            self.ImageUpdate.emit(image)


app = QApplication(sys.argv)
mw = MainWindow()
# mw.show()
sys.exit(app.exec_())

当我运行此程序时,实际程序运行良好,但几秒钟后它会自动关闭

进程已完成,退出代码为 -1073741819 (0xC0000005)

块引用

奇怪的是,在 PyCharm 中调试代码时,它没有关闭。但每当我运行代码时,它都会在几秒钟后自动关闭。任何帮助将不胜感激。

python oop pyqt pyqt5
2个回答
0
投票

这些总是很难排除故障,但我发现您应该在初始化应用程序时避免使用 QThreads,因为它有时会导致随机关闭。

尝试:

  • 初始化应用程序并显示它。
  • 运行网络摄像头类(尽管我建议您用函数替换它)

如果您想让此功能线程化,这样就不会锁定 UI,请查看 PyQt5 的 QThreadPool (https://www.mfitzp.com/tutorials/multithreading-pyqt-applications-qthreadpool/)


0
投票

使用QTHereadPool 这是在 PyQt5 中使用 QThreadPool 的示例:

导入系统 从 PyQt5.QtCore 导入 QThreadPool、QRunnable、pyqtSignal、QObject、QTimer 从 PyQt5.QtWidgets 导入 QApplication、QMainWindow、QLabel、QVBoxLayout、QPushButton、QWidget

class WorkerSignals(QObject):
    finished = pyqtSignal()

class Worker(QRunnable):
    def __init__(self):
        super().__init__()
        self.signals = WorkerSignals()

def run(self):
    import time
    time.sleep(5)  # Simulating a long-running task
    self.signals.finished.emit()

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("QThreadPool Example")
        self.setGeometry(100, 100, 400, 200)

        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)

        self.label = QLabel("Waiting")
        self.button = QPushButton("Start Thread Pool")
        self.button.clicked.connect(self.start_thread_pool)

        layout = QVBoxLayout()
        layout.addWidget(self.label)
        layout.addWidget(self.button)
        self.central_widget.setLayout(layout)

        self.threadpool = QThreadPool()

    def start_thread_pool(self):
        self.label.setText("Thread Pool Started")
        self.button.setEnabled(False)

        # Submitting tasks to the thread pool
        for _ in range(5):
            worker = Worker()
            worker.signals.finished.connect(self.worker_finished)
            self.threadpool.start(worker)

    def worker_finished(self):
        QTimer.singleShot(0, lambda: self.label.setText("All tasks completed"))
        self.button.setEnabled(True)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

在这个例子中,我们创建了一个继承自QRunnable的Worker类。每个工作人员模拟一个长时间运行的任务(睡眠 5 秒),并在任务完成时发出完成信号。我们将此信号连接到主窗口 (worker_finished) 中的一个槽,我们在其中更新标签以指示所有任务均已完成。

当点击“Start Thread Pool”按钮时,我们创建多个 Worker 实例,并使用 start() 方法将它们提交到 QThreadPool。然后,线程池有效地管理这些任务的执行。

PyQt(或一般 Qt)中

QThread
QThreadPool
之间的主要区别在于它们的用途和使用场景:

  1. QThread

    • 代表单线程执行。
    • 通常用于运行需要异步或在后台执行的单个任务或操作。
    • 直接管理单个线程的生命周期,包括启动、暂停、停止。
    • 提供对各个线程的较低级别控制,允许开发人员实现自定义线程行为。
  2. QThreadPool

    • 表示一个线程池,可用于并发执行多个任务。
    • 适合有多个类似任务并行执行的场景,例如处理多个网络请求或同时处理多个数据项。
    • 管理工作线程池并将任务分配给可用线程执行,从而提供更好的资源利用率。
    • QThread
      相比,提供了更高级别的抽象,抽象出线程管理的细节,让开发人员专注于定义要执行的任务。

总而言之,虽然

QThread
适合管理单个线程和执行单个任务,但
QThreadPool
更适合通过有效利用线程池来同时管理多个任务。它们之间的选择取决于应用程序的具体要求和要执行的任务的性质。

© www.soinside.com 2019 - 2024. All rights reserved.