QQuickPaintedItem崩溃不渲染怎么解决?
How to solve QQuickPaintedItem crash and not rendering?
我尝试显示预处理图像流,所以我创建了一个自定义 QQuickPaintedItem
来绘制图像
问题是,当图像发生变化时,什么也没有发生,只是应用程序崩溃了,但 paint 方法的打印语句仍在打印,鼠标光标看起来像 +
符号。
这是我的 LiveCamera
来自 QQuickPaintedItem
的子类
class LiveCamera(QQuickPaintedItem):
imageChanged=Signal(QImage)
def __init__(self):
super().__init__()
self.setRenderTarget(QQuickPaintedItem.FramebufferObject)
self.m_image = QImage("C://Users//Hassan//Documents//python-gui-projects//PortMafiaSecurity//images//loading.jpg")
def paint(self,painter: QPainter):
print('hey')
if self.m_image.isNull(): return
img = self.m_image.scaled(self.size().toSize(),Qt.KeepAspectRatioByExpanding ,Qt.SmoothTransformation)
painter.drawPixmap(QPoint(),QPixmap.fromImage(img))
@Property(QImage, notify=imageChanged)
def image(self):
return self.m_image
@image.setter
def image(self, image):
if self.m_image == image: return
self.m_image = image
self.imageChanged.emit(self.m_image)
#self.paint(QPainter())
self.update()
这里是main.py
class CamThread(QThread):
def __init__(self,UI):
super().__init__()
self.UI=UI
def run(self):
cap = open_images_capture(args.input, args.loop)
frame_processor = FrameProcessor(args)
frame_num = 0
output_transform = None
while True:
start_time = perf_counter()
frame = cap.read()
if frame_num == 0:
output_transform = OutputTransform(frame.shape[:2], args.output_resolution)
detections = frame_processor.process(frame)
frame = draw_detections(frame, frame_processor, detections, output_transform)
frame_num += 1
h, w, ch = frame.shape
p = QImage(frame.data, h, w,QImage.Format_RGB888)
self.UI.changeImage.emit(p)
class MainThread(QObject):
def __init__(self):
QObject.__init__(self)
self.cam=CamThread(self)
changeImage=Signal(QImage)
@Slot(bool)
def click(self,first):
if first:
self.cam.run()
else:
self.cam.quit()
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
main = MainThread()
engine.rootContext().setContextProperty("cam_recording", main)
qmlRegisterType(LiveCamera, "LiveCameraPlugin", 1, 0, "LiveCamera")
engine.load(os.fspath(Path(__file__).resolve().parent / "qml/main.qml"))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
这是Qml
Rectangle{
x: 72
y: 84
width: 649
height: 366
LiveCamera{
id:camera
anchors.fill: parent
}
}
LeftMenuBtn {
//some stuff
}
Connections{
target: cam_recording
function onChangeImage(img){
camera.image=img
}
}
有没有解决这个问题的方法,我尝试了很多方法来寻找解决方案,但我也没有找到我也试过 QtQuickImageProvider
同样的问题,请问有更好的方法吗?
这里是Application Crash Moment: Python is not responding
根据屏幕截图,这不是崩溃。该程序似乎太忙(在 main/gui 线程上)无法响应用户交互,导致 Windows 表示应用程序没有响应。
要调试这样的问题,你应该使用调试器,暂停程序,看看他在做什么(在主线程上)。
在这种情况下,问题是您在主线程中 运行 CamThread::run
(执行无限循环),而不是在单独的线程中 运行如预期。您不应显式调用 QThread::run
,而应调用 QThread::start
,这将启动一个新线程并在该新线程上执行 QThread::run
函数。
请注意 QThread::quit
does nothing in your case, as by reimplementing QThread::run
,QEventLoop
并未在该线程上启动。您应该启动事件循环,或者您应该实现自己的信号,以中断 CamThread::run
内的无限循环,让线程优雅地完成。
我尝试显示预处理图像流,所以我创建了一个自定义 QQuickPaintedItem
来绘制图像
问题是,当图像发生变化时,什么也没有发生,只是应用程序崩溃了,但 paint 方法的打印语句仍在打印,鼠标光标看起来像 +
符号。
这是我的 LiveCamera
来自 QQuickPaintedItem
class LiveCamera(QQuickPaintedItem):
imageChanged=Signal(QImage)
def __init__(self):
super().__init__()
self.setRenderTarget(QQuickPaintedItem.FramebufferObject)
self.m_image = QImage("C://Users//Hassan//Documents//python-gui-projects//PortMafiaSecurity//images//loading.jpg")
def paint(self,painter: QPainter):
print('hey')
if self.m_image.isNull(): return
img = self.m_image.scaled(self.size().toSize(),Qt.KeepAspectRatioByExpanding ,Qt.SmoothTransformation)
painter.drawPixmap(QPoint(),QPixmap.fromImage(img))
@Property(QImage, notify=imageChanged)
def image(self):
return self.m_image
@image.setter
def image(self, image):
if self.m_image == image: return
self.m_image = image
self.imageChanged.emit(self.m_image)
#self.paint(QPainter())
self.update()
这里是main.py
class CamThread(QThread):
def __init__(self,UI):
super().__init__()
self.UI=UI
def run(self):
cap = open_images_capture(args.input, args.loop)
frame_processor = FrameProcessor(args)
frame_num = 0
output_transform = None
while True:
start_time = perf_counter()
frame = cap.read()
if frame_num == 0:
output_transform = OutputTransform(frame.shape[:2], args.output_resolution)
detections = frame_processor.process(frame)
frame = draw_detections(frame, frame_processor, detections, output_transform)
frame_num += 1
h, w, ch = frame.shape
p = QImage(frame.data, h, w,QImage.Format_RGB888)
self.UI.changeImage.emit(p)
class MainThread(QObject):
def __init__(self):
QObject.__init__(self)
self.cam=CamThread(self)
changeImage=Signal(QImage)
@Slot(bool)
def click(self,first):
if first:
self.cam.run()
else:
self.cam.quit()
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
main = MainThread()
engine.rootContext().setContextProperty("cam_recording", main)
qmlRegisterType(LiveCamera, "LiveCameraPlugin", 1, 0, "LiveCamera")
engine.load(os.fspath(Path(__file__).resolve().parent / "qml/main.qml"))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
这是Qml
Rectangle{
x: 72
y: 84
width: 649
height: 366
LiveCamera{
id:camera
anchors.fill: parent
}
}
LeftMenuBtn {
//some stuff
}
Connections{
target: cam_recording
function onChangeImage(img){
camera.image=img
}
}
有没有解决这个问题的方法,我尝试了很多方法来寻找解决方案,但我也没有找到我也试过 QtQuickImageProvider
同样的问题,请问有更好的方法吗?
这里是Application Crash Moment: Python is not responding
根据屏幕截图,这不是崩溃。该程序似乎太忙(在 main/gui 线程上)无法响应用户交互,导致 Windows 表示应用程序没有响应。
要调试这样的问题,你应该使用调试器,暂停程序,看看他在做什么(在主线程上)。
在这种情况下,问题是您在主线程中 运行 CamThread::run
(执行无限循环),而不是在单独的线程中 运行如预期。您不应显式调用 QThread::run
,而应调用 QThread::start
,这将启动一个新线程并在该新线程上执行 QThread::run
函数。
请注意 QThread::quit
does nothing in your case, as by reimplementing QThread::run
,QEventLoop
并未在该线程上启动。您应该启动事件循环,或者您应该实现自己的信号,以中断 CamThread::run
内的无限循环,让线程优雅地完成。