Added Worker to GUI process for time-consuming tasks (e.g. printing) to make GUI more responsive
This commit is contained in:
@@ -316,22 +316,22 @@ class CountdownMessage(QtWidgets.QFrame):
|
|||||||
|
|
||||||
class PostprocessMessage(Widgets.TransparentOverlay):
|
class PostprocessMessage(Widgets.TransparentOverlay):
|
||||||
|
|
||||||
def __init__(self, parent, tasks, idle_handle, timeout=None,
|
def __init__(self, parent, tasks, worker, idle_handle,
|
||||||
timeout_handle=None):
|
timeout=None, timeout_handle=None):
|
||||||
|
|
||||||
if timeout_handle is None:
|
if timeout_handle is None:
|
||||||
timeout_handle = idle_handle
|
timeout_handle = idle_handle
|
||||||
|
|
||||||
super().__init__(parent, timeout, timeout_handle)
|
super().__init__(parent, timeout, timeout_handle)
|
||||||
self.setObjectName('PostprocessMessage')
|
self.setObjectName('PostprocessMessage')
|
||||||
self.initFrame(tasks, idle_handle)
|
self.initFrame(tasks, idle_handle, worker)
|
||||||
|
|
||||||
def initFrame(self, tasks, idle_handle):
|
def initFrame(self, tasks, idle_handle, worker):
|
||||||
|
|
||||||
def disableAndCall(button, handle):
|
def disableAndCall(button, handle):
|
||||||
button.setEnabled(False)
|
button.setEnabled(False)
|
||||||
button.update()
|
button.update()
|
||||||
handle()
|
worker.put(handle)
|
||||||
|
|
||||||
def createButton(task):
|
def createButton(task):
|
||||||
button = QtWidgets.QPushButton(task.label)
|
button = QtWidgets.QPushButton(task.label)
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ from ..GuiPostprocessor import GuiPostprocessor
|
|||||||
from . import styles
|
from . import styles
|
||||||
from . import Frames
|
from . import Frames
|
||||||
from . import Receiver
|
from . import Receiver
|
||||||
|
from . import Worker
|
||||||
|
|
||||||
|
|
||||||
class PyQt5Gui(GuiSkeleton):
|
class PyQt5Gui(GuiSkeleton):
|
||||||
@@ -49,6 +50,7 @@ class PyQt5Gui(GuiSkeleton):
|
|||||||
is_start, unparsed_args = self._parseArgs()
|
is_start, unparsed_args = self._parseArgs()
|
||||||
self._initUI(argv[:1] + unparsed_args)
|
self._initUI(argv[:1] + unparsed_args)
|
||||||
self._initReceiver()
|
self._initReceiver()
|
||||||
|
self._initWorker()
|
||||||
|
|
||||||
self._picture = None
|
self._picture = None
|
||||||
self._postprocess = GuiPostprocessor(self._cfg)
|
self._postprocess = GuiPostprocessor(self._cfg)
|
||||||
@@ -101,6 +103,12 @@ class PyQt5Gui(GuiSkeleton):
|
|||||||
self._receiver.notify.connect(self.handleState)
|
self._receiver.notify.connect(self.handleState)
|
||||||
self._receiver.start()
|
self._receiver.start()
|
||||||
|
|
||||||
|
def _initWorker(self):
|
||||||
|
|
||||||
|
# Create worker thread for time consuming tasks to keep gui responsive
|
||||||
|
self._worker = Worker.Worker(self._comm)
|
||||||
|
self._worker.start()
|
||||||
|
|
||||||
def _enableEscape(self):
|
def _enableEscape(self):
|
||||||
|
|
||||||
self._is_escape = True
|
self._is_escape = True
|
||||||
@@ -131,6 +139,7 @@ class PyQt5Gui(GuiSkeleton):
|
|||||||
if state.target == TeardownEvent.WELCOME:
|
if state.target == TeardownEvent.WELCOME:
|
||||||
self._comm.send(Workers.MASTER, GuiEvent('welcome'))
|
self._comm.send(Workers.MASTER, GuiEvent('welcome'))
|
||||||
elif state.target in (TeardownEvent.EXIT, TeardownEvent.RESTART):
|
elif state.target in (TeardownEvent.EXIT, TeardownEvent.RESTART):
|
||||||
|
self._worker.put(None)
|
||||||
self._app.exit(0)
|
self._app.exit(0)
|
||||||
|
|
||||||
def showError(self, state):
|
def showError(self, state):
|
||||||
@@ -229,7 +238,7 @@ class PyQt5Gui(GuiSkeleton):
|
|||||||
postproc_t = self._cfg.getInt('Photobooth', 'postprocess_time')
|
postproc_t = self._cfg.getInt('Photobooth', 'postprocess_time')
|
||||||
|
|
||||||
Frames.PostprocessMessage(
|
Frames.PostprocessMessage(
|
||||||
self._gui.centralWidget(), tasks,
|
self._gui.centralWidget(), tasks, self._worker,
|
||||||
lambda: self._comm.send(Workers.MASTER, GuiEvent('idle')),
|
lambda: self._comm.send(Workers.MASTER, GuiEvent('idle')),
|
||||||
postproc_t * 1000)
|
postproc_t * 1000)
|
||||||
|
|
||||||
|
|||||||
52
photobooth/gui/Qt5Gui/Worker.py
Normal file
52
photobooth/gui/Qt5Gui/Worker.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Photobooth - a flexible photo booth software
|
||||||
|
# Copyright (C) 2018 Balthasar Reuter <photobooth at re - web dot eu>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import queue
|
||||||
|
|
||||||
|
from PyQt5 import QtCore
|
||||||
|
|
||||||
|
|
||||||
|
class Worker(QtCore.QThread):
|
||||||
|
|
||||||
|
def __init__(self, comm):
|
||||||
|
|
||||||
|
super().__init__()
|
||||||
|
self._comm = comm
|
||||||
|
self._queue = queue.Queue()
|
||||||
|
|
||||||
|
def put(self, task):
|
||||||
|
|
||||||
|
self._queue.put(task)
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
|
||||||
|
return self._queue.get()
|
||||||
|
|
||||||
|
def done(self):
|
||||||
|
|
||||||
|
self._queue.task_done()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
|
||||||
|
while True:
|
||||||
|
task = self.get()
|
||||||
|
if task is None:
|
||||||
|
break
|
||||||
|
task()
|
||||||
|
self.done()
|
||||||
Reference in New Issue
Block a user