【问题标题】:RuntimeError: wrapped C/C++ object of type QLabel has been deletedRuntimeError: QLabel 类型的包装 C/C++ 对象已被删除
【发布时间】:2020-11-10 17:09:28
【问题描述】:

我正在尝试运行以下代码,但它给了我一个错误RuntimeError: QLabel 类型的包装 C/C++ 对象已被删除。我无法弄清楚为什么会这样。

我搜索了其他答案,但他们都说这与 setCentralWidget 有关。但我没有使用它。那么,为什么我的代码会出现错误?

from PyQt4 import QtGui, QtCore
from threading import Thread
from collections import deque
from datetime import datetime
import time
import sys
import cv2
import imutils
import os


class CameraWidget(QtGui.QWidget):
    """Independent camera feed
    Uses threading to grab IP camera frames in the background

    @param width - Width of the video frame
    @param height - Height of the video frame
    @param stream_link - IP/RTSP/Webcam link
    @param aspect_ratio - Whether to maintain frame aspect ratio or force into fraame
    """

    def __init__(self, width, height, stream_link=0, btn_text=None, aspect_ratio=False, parent=None, deque_size=1):
        super(CameraWidget, self).__init__(parent)

        # Initialize deque used to store frames read from the stream
        self.deque = deque(maxlen=deque_size)

        self.screen_width = width - 8  
        self.screen_height = height - 8
        self.maintain_aspect_ratio = aspect_ratio

        self.camera_stream_link = stream_link

        # Flag to check if camera is valid/working
        self.online = False
        self.capture = None

        self.video_display_frame = QtGui.QFrame()
        self.video_layout = QtGui.QVBoxLayout()
        self.video_btn = QtGui.QPushButton(btn_text)
        self.video_btn.setStyleSheet("background-color: rgb(128, 159, 255)")
        self.video_btn.clicked.connect(self.message)
        self.video_frame = QtGui.QLabel()
        self.video_layout.addWidget(self.video_btn)
        self.video_layout.addWidget(self.video_frame)
        self.video_layout.setContentsMargins(0,0,0,0)
        self.video_layout.setSpacing(0)
        self.video_display_frame.setLayout(self.video_layout)

        self.load_network_stream()

        # Start background frame grabbing
        self.get_frame_thread = Thread(target=self.get_frame, args=())
        self.get_frame_thread.daemon = True
        self.get_frame_thread.start()

        # Periodically set video frame to display
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.set_frame)
        self.timer.start(.5)

        print('Started camera: {}'.format(self.camera_stream_link))

    def load_network_stream(self):
        """Verifies stream link and open new stream if valid"""

        def load_network_stream_thread():
            if self.verify_network_stream(self.camera_stream_link):
                self.capture = cv2.VideoCapture(self.camera_stream_link)
                self.online = True
        self.load_stream_thread = Thread(target=load_network_stream_thread, args=())
        self.load_stream_thread.daemon = True
        self.load_stream_thread.start()

    def verify_network_stream(self, link):
        """Attempts to receive a frame from given link"""

        cap = cv2.VideoCapture(link)
        if not cap.isOpened():
            return False
        cap.release()
        return True

    def get_frame(self):
        """Reads frame, resizes, and converts image to pixmap"""

        while True:
            try:
                if self.capture.isOpened() and self.online:
                    # Read next frame from stream and insert into deque
                    status, frame = self.capture.read()
                    if status:
                        self.deque.append(frame)
                    else:
                        self.capture.release()
                        self.online = False
                else:
                    # Attempt to reconnect
                    print('attempting to reconnect', self.camera_stream_link)
                    self.load_network_stream()
                    self.spin(2)
                self.spin(.001)
            except AttributeError:
                pass

    def spin(self, seconds):
        """Pause for set amount of seconds, replaces time.sleep so program doesnt stall"""

        time_end = time.time() + seconds
        while time.time() < time_end:
            QtGui.QApplication.processEvents()

    def set_frame(self):
        """Sets pixmap image to video frame"""

        if not self.online:
            self.spin(1)
            return

        if self.deque and self.online:
            # Grab latest frame
            frame = self.deque[-1]

            # Keep frame aspect ratio
            if self.maintain_aspect_ratio:
                self.frame = imutils.resize(frame, width=self.screen_width)
            # Force resize
            else:
                self.frame = cv2.resize(frame, (self.screen_width, self.screen_height))

            # Convert to pixmap and set to video frame
            self.img = QtGui.QImage(self.frame, self.frame.shape[1], self.frame.shape[0], QtGui.QImage.Format_RGB888).rgbSwapped()
            self.pix = QtGui.QPixmap.fromImage(self.img)
            self.video_frame.setPixmap(self.pix)                  ### error comes in this line.

    def get_video_frame(self):
        return self.video_frame

    def get_video_display_frame(self):
        return self.video_display_frame

    def message(self):
        self.zone_config = ZoneConfig(self.camera_stream_link) 
        self.zone_config.show()


class MainWindow(QtGui.QWidget):    

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.initUI()

    def initUI(self):
        self.setWindowTitle("VIDS")
        titleBar_logo = os.path.join(dir, 'logos/logo.png')
        self.setWindowIcon(QtGui.QIcon(titleBar_logo))
        self.showMaximized()

        self.screen_width = self.width()
        self.screen_height = self.height()

        # Layouts & frames
        self.layout = QtGui.QVBoxLayout()

        self.top_frame = QtGui.QFrame()
        self.top_frame.setStyleSheet("background-color: rgb(208, 208, 225)")
        self.mid_frame = QtGui.QFrame()   
        self.mid_frame.setStyleSheet("background-color: rgb(153, 187, 255)")
        self.btm_frame = QtGui.QFrame()
        self.btm_frame.setStyleSheet("background-color: rgb(208, 208, 225)")

        self.layout.addWidget(self.top_frame, 2)
        self.layout.addWidget(self.mid_frame, 20)
        self.layout.addWidget(self.btm_frame, 1)

        self.layout.setContentsMargins(0,0,0,0)
        self.layout.setSpacing(0)
        self.setLayout(self.layout)

        # Top frame
        label = QtGui.QLabel('VIDS Dashboard')
        label.setFont(QtGui.QFont('Arial', 20))
        label.setAlignment(QtCore.Qt.AlignCenter)

        self.top_layout = QtGui.QHBoxLayout()
        self.top_layout.addWidget(label)
        self.top_frame.setLayout(self.top_layout)

        # Middle frame
        self.mid_layout = QtGui.QStackedLayout()

        # Create camera widgets
        print('Creating Camera Widgets...')
        self.one = CameraWidget(int(self.screen_width), int(self.screen_height), camera1, 'Camera 1')
        self.two = CameraWidget(int(self.screen_width), int(self.screen_height), camera2, 'Camera 2')

        cam_widget = Cam2(self.one, self.two, self)
        self.mid_layout.addWidget(cam_widget)
        self.mid_layout.setCurrentWidget(cam_widget)
        self.mid_frame.setLayout(self.mid_layout)  

        # Bottom frame
        btn1 = QtGui.QPushButton('1 Cam')
        btn1.clicked.connect(self.button1)
        btn2 = QtGui.QPushButton('2 Cams')
        btn2.clicked.connect(self.button2)

        self.btm_layout = QtGui.QHBoxLayout()
        self.btm_layout.addStretch()
        self.btm_layout.addWidget(btn1)
        self.btm_layout.addWidget(btn2)
        self.btm_frame.setLayout(self.btm_layout)
        self.show()

    def button1(self):
        cam1_widget = Cam1(self.one, self)
        self.mid_layout.addWidget(cam1_widget)
        self.mid_layout.setCurrentWidget(cam1_widget)

    def button2(self):
        cam2_widget = Cam2(self.one, self.two, self)
        self.mid_layout.addWidget(cam2_widget)
        self.mid_layout.setCurrentWidget(cam2_widget)


class Cam1(QtGui.QWidget):
    def __init__(self, one, parent=None):
        super(Cam1, self).__init__(parent)

        # Add widgets to layout
        print('Adding widgets to layout...')
        layout = QtGui.QGridLayout()
        layout.addWidget(one.get_video_display_frame(),0,0,1,1)
        self.setLayout(layout)


class Cam2(QtGui.QWidget):
    def __init__(self, one, two, parent=None):
        super(Cam2, self).__init__(parent)

        # Add widgets to layout
        print('Adding widgets to layout...')
        layout = QtGui.QGridLayout()
        layout.addWidget(one.get_video_display_frame(),0,0,1,1)
        layout.addWidget(two.get_video_display_frame(),0,1,1,1)
        self.setLayout(layout)


class ZoneConfig(QtGui.QWidget):
    def __init__(self, camera, parent=None):
        super(ZoneConfig, self).__init__(parent)

        self.initUI(camera)

    def initUI(self, camera):

        self.setWindowTitle("VIDS")
        titleBar_logo = os.path.join(dir, 'logos/logo.png')
        self.setWindowIcon(QtGui.QIcon(titleBar_logo))
        self.showMaximized()

        self.screen_width = self.width()
        self.screen_height = self.height()
        
        self.camera = camera

        # Layouts & frames
        self.layout = QtGui.QVBoxLayout()

        self.top_frame = QtGui.QFrame()
        self.top_frame.setStyleSheet("background-color: rgb(208, 208, 225)")
        self.mid_frame = QtGui.QFrame()   
        # self.mid_frame.setStyleSheet("background-color: rgb(153, 187, 255)")
        self.btm_frame = QtGui.QFrame()
        self.btm_frame.setStyleSheet("background-color: rgb(208, 208, 225)")

        self.layout.addWidget(self.top_frame, 2)
        self.layout.addWidget(self.mid_frame, 20)
        self.layout.addWidget(self.btm_frame, 1)

        self.layout.setContentsMargins(0,0,0,0)
        self.layout.setSpacing(0)
        self.setLayout(self.layout)        

        # Top frame
        self.label = QtGui.QLabel('VIDS - Zone Configuration')
        self.label.setFont(QtGui.QFont('Arial', 20))
        self.label.setAlignment(QtCore.Qt.AlignCenter)

        self.top_layout = QtGui.QHBoxLayout()
        self.top_layout.addWidget(self.label)
        self.top_frame.setLayout(self.top_layout)

        # Middle frame
        self.mid_layout = QtGui.QVBoxLayout()
        self.mid_frame.setStyleSheet("background-color: rgb(153, 187, 255)")

        # Create camera widgets
        print('Creating Camera Widgets...')
        self.cam = CameraWidget(self.screen_width, self.screen_height, self.camera)

        self.mid_layout = QtGui.QVBoxLayout()
        self.mid_layout.addWidget(self.cam.get_video_frame())
        self.mid_frame.setLayout(self.mid_layout)

        self.mid_layout.setContentsMargins(0,0,0,0)
        self.mid_layout.setSpacing(0)
        self.mid_frame.setLayout(self.mid_layout)   
        
        # Bottom frame
        btn = QtGui.QPushButton('Dashboard')
        btn.clicked.connect(self.goMainWindow)

        self.btm_layout = QtGui.QHBoxLayout()
        self.btm_layout.addStretch()
        self.btm_layout.addWidget(btn)
        self.btm_frame.setLayout(self.btm_layout)

    def goMainWindow(self):
        self.close()


dir = os.path.dirname(__file__)
window = None
camera1 = 'streams/Fog.avi'
camera2 = 'streams/Overspeed.avi'


if __name__ == '__main__':
    app = QtGui.QApplication([])
    app.setStyle(QtGui.QStyleFactory.create("plastique"))                            # applies to entire window 
    window = MainWindow()
    # window.show()
    sys.exit(app.exec_())

我正在使用 python 3、pyqt 4 和 windows 10。

【问题讨论】:

  • 我无法测试您的代码,但无论如何我都会避免使用global,尤其是创建新实例(这可能是您的问题的原因):window 对象已经存在,你不应该创建新的。
  • @musicamante,我已经通过删除 global 更新了我的代码,但问题仍然存在。

标签: python python-3.x pyqt pyqt4


【解决方案1】:

似乎在线程的处理中它并没有正确同步对象的消除,所以一个可能的解决方案是使用 sip 来验证对象是否被消除:

from PyQt4 import QtGui, QtCore
import sip
# ...
self.pix = QtGui.QPixmap.fromImage(self.img)
if not sip.isdeleted(self.video_frame):
    self.video_frame.setPixmap(self.pix)

【讨论】:

    猜你喜欢
    • 2021-10-03
    • 2019-06-05
    • 2020-08-29
    • 1970-01-01
    • 2021-06-02
    • 1970-01-01
    • 2013-07-28
    • 2020-06-01
    • 1970-01-01
    相关资源
    最近更新 更多