Added Worker to GUI process for time-consuming tasks (e.g. printing) to make GUI more responsive

This commit is contained in:
Balthasar Reuter
2018-07-27 15:56:15 +02:00
parent 884df55a22
commit 681037d3d3
3 changed files with 67 additions and 6 deletions

View File

@@ -316,22 +316,22 @@ class CountdownMessage(QtWidgets.QFrame):
class PostprocessMessage(Widgets.TransparentOverlay):
def __init__(self, parent, tasks, idle_handle, timeout=None,
timeout_handle=None):
def __init__(self, parent, tasks, worker, idle_handle,
timeout=None, timeout_handle=None):
if timeout_handle is None:
timeout_handle = idle_handle
super().__init__(parent, timeout, timeout_handle)
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):
button.setEnabled(False)
button.update()
handle()
worker.put(handle)
def createButton(task):
button = QtWidgets.QPushButton(task.label)

View File

@@ -36,6 +36,7 @@ from ..GuiPostprocessor import GuiPostprocessor
from . import styles
from . import Frames
from . import Receiver
from . import Worker
class PyQt5Gui(GuiSkeleton):
@@ -49,6 +50,7 @@ class PyQt5Gui(GuiSkeleton):
is_start, unparsed_args = self._parseArgs()
self._initUI(argv[:1] + unparsed_args)
self._initReceiver()
self._initWorker()
self._picture = None
self._postprocess = GuiPostprocessor(self._cfg)
@@ -101,6 +103,12 @@ class PyQt5Gui(GuiSkeleton):
self._receiver.notify.connect(self.handleState)
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):
self._is_escape = True
@@ -131,6 +139,7 @@ class PyQt5Gui(GuiSkeleton):
if state.target == TeardownEvent.WELCOME:
self._comm.send(Workers.MASTER, GuiEvent('welcome'))
elif state.target in (TeardownEvent.EXIT, TeardownEvent.RESTART):
self._worker.put(None)
self._app.exit(0)
def showError(self, state):
@@ -229,7 +238,7 @@ class PyQt5Gui(GuiSkeleton):
postproc_t = self._cfg.getInt('Photobooth', 'postprocess_time')
Frames.PostprocessMessage(
self._gui.centralWidget(), tasks,
self._gui.centralWidget(), tasks, self._worker,
lambda: self._comm.send(Workers.MASTER, GuiEvent('idle')),
postproc_t * 1000)

View 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()