I try to show stream of preprocessed Images so I create custom QQuickPaintedItem to paint images The problem that when image change ,Nothing happen just application crashed but print statement of paint method still print and mouse cursor look like sign.
here is my LiveCamera subclass from 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()
Here is 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_())
Here is 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
}
Is there a way to solve that problem ,I tried a lot to search for solution but I didn't find also I tried QtQuickImageProvider same problem so is there better way?
Here is Application Crash Moment
CodePudding user response:
According to the screenshot, this isn't a crash. The program seems to be to busy (on the main/gui thread) to respond to user interaction, resulting in Windows saying the application is not responsive.
To debug such a problem, you should use a debugger, pause the program and see what he is doing (on the main thread).
The problem in this case is that you are running CamThread::run
(which executes an infinite loop) inside the main thread, instead of running it on a separate thread as intended. You shouldn't call QThread::run
explicitly, but call QThread::start
, which will start a new thread and execute the QThread::run
function on that new thread.
Note that QThread::quit
does nothing in your case, as by reimplementing QThread::run
, the QEventLoop
isn't started on that thread. Either you should start the event loop or you should implement your own signal, to interrupt the infinite loop inside CamThread::run
to let the thread finish gracefull.