RuntimeError: wrapped C/C++ object of type QLabel has been deleted
RuntimeError: wrapped C/C++ object of type QLabel has been deleted
我正在尝试 运行 下面的代码,但它给我一个错误 RuntimeError: wrapped C/C++ QLabel 类型的对象已被删除.我无法弄清楚为什么会这样。
我搜索了其他答案,但他们都说与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。
好像在线程的处理上没有正确同步对象的消除,所以一个可能的解决办法是用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)
我正在尝试 运行 下面的代码,但它给我一个错误 RuntimeError: wrapped C/C++ QLabel 类型的对象已被删除.我无法弄清楚为什么会这样。
我搜索了其他答案,但他们都说与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。
好像在线程的处理上没有正确同步对象的消除,所以一个可能的解决办法是用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)