From 0688fa5fa685394f338f0712d848bfe474be41a8 Mon Sep 17 00:00:00 2001 From: Balthasar Reuter Date: Wed, 21 Mar 2018 22:09:37 +0100 Subject: [PATCH] Multiprocessing to separate Photobooth logic and GUI. Pipes to connect them to each other --- photobooth/Photobooth.py | 60 ++++++++++++++++- photobooth/PyQt5Gui.py | 135 +++++++++++++++++++++++++++++++++------ 2 files changed, 174 insertions(+), 21 deletions(-) diff --git a/photobooth/Photobooth.py b/photobooth/Photobooth.py index 9ba51be..ff09b85 100644 --- a/photobooth/Photobooth.py +++ b/photobooth/Photobooth.py @@ -1,9 +1,63 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import Config, PyQt5Gui +from Config import Config +from PyQt5Gui import PyQt5Gui + +from multiprocessing import Pipe, Process + +from time import sleep + + +class Photobooth: + + def __init__(self): + + pass + + + def run(self, send, recv): + + while True: + try: + event = recv.recv() + except EOFError: + return 1 + else: + print('Photobooth: ' + event) + self.trigger(send) + + return 0 + + + def trigger(self, send): + + send.send('Pose') + + sleep(3) + + send.send('Picture') + + sleep(2) + + send.send('idle') + + +def main_photobooth(send, recv): + + photobooth = Photobooth() + return photobooth.run(send, recv) + def main(argv): - config = Config.Config('photobooth.cfg') - return PyQt5Gui.run(argv, config) + config = Config('photobooth.cfg') + + event_recv, event_send = Pipe(duplex=False) + gui_recv, gui_send = Pipe(duplex=False) + + photobooth = Process(target=main_photobooth, args=(gui_send, event_recv), daemon=True) + photobooth.start() + + gui = PyQt5Gui(argv, config) + return gui.run(event_send, gui_recv) diff --git a/photobooth/PyQt5Gui.py b/photobooth/PyQt5Gui.py index 6c3b8a3..11c0764 100644 --- a/photobooth/PyQt5Gui.py +++ b/photobooth/PyQt5Gui.py @@ -1,10 +1,62 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from PyQt5.QtCore import Qt +from PyQt5.QtCore import Qt, QObject, QThread, pyqtSignal from PyQt5.QtWidgets import (QApplication, QCheckBox, QComboBox, QFormLayout, QFrame, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLayout, QLineEdit, QMainWindow, QMessageBox, QPushButton, QVBoxLayout) +from PyQt5.QtGui import QPainter, QPixmap -class PyQt5Gui(QMainWindow): +class PyQt5Gui: + + def __init__(self, argv, config): + + global cfg + cfg = config + + self._app = QApplication(argv) + self._p = PyQt5MainWindow() + + + def run(self, send, recv): + + receiver = PyQt5Receiver(recv) + receiver.notify.connect(self._p.showMessage) + receiver.start() + + self._p.transport = send + + return self._app.exec_() + + +class PyQt5Receiver(QThread): + + notify = pyqtSignal(object) + + def __init__(self, transport): + + super().__init__() + + self._transport = transport + + + def handle(self, event): + + self.notify.emit(event) + + + def run(self): + + while True: + try: + event = self._transport.recv() + except EOFError: + break + else: + print('Connector: ' + event) + self.handle(event) + + + +class PyQt5MainWindow(QMainWindow): def __init__(self): @@ -13,6 +65,21 @@ class PyQt5Gui(QMainWindow): self.initUI() + @property + def transport(self): + + return self._transport + + + @transport.setter + def transport(self, new_transport): + + if not hasattr(new_transport, 'send'): + raise ValueError('PyQt5MainWindow.transport must provide send()') + + self._transport = new_transport + + def initUI(self): global cfg @@ -40,24 +107,35 @@ class PyQt5Gui(QMainWindow): self.setCentralWidget(content) + def showIdle(self): + + self.showMessage('Hit the button!', 'homer.jpg') + + + def showMessage(self, message, picture=None): + + content = PyQt5PictureMessage(message, picture) + self.setCentralWidget(content) + + def closeEvent(self, e): reply = QMessageBox.question(self, 'Confirmation', "Quit Photobooth?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: + self.transport.close() e.accept() else: e.ignore() - def keyPressEvent(self, e): - pass - # if self.photobooth.status == Status.idle: - # if e.key() == Qt.Key_Escape: - # self.showStart() - # elif e.key() == Qt.Key_Space: - # self.centralWidget().trigger() + def keyPressEvent(self, event): + + if event.key() == Qt.Key_Escape: + self.showStart() + elif event.key() == Qt.Key_Space: + self.transport.send('triggered') @@ -66,7 +144,7 @@ class PyQt5Start(QFrame): def __init__(self, parent): - super().__init__(parent) + super().__init__() self.initFrame(parent) @@ -79,7 +157,7 @@ class PyQt5Start(QFrame): btnStart = QPushButton('Start Photobooth') btnStart.resize(btnStart.sizeHint()) - # btnStart.clicked.connect(parent.showPhotobooth) + btnStart.clicked.connect(parent.showIdle) grid.addWidget(btnStart, 0, 0) btnSettings = QPushButton('Settings') @@ -98,7 +176,7 @@ class PyQt5Settings(QFrame): def __init__(self, parent): - super().__init__(parent) + super().__init__() self._parent = parent self.initFrame() @@ -247,11 +325,32 @@ class PyQt5Settings(QFrame): self._parent.showSettings() -def run(argv, config): - global cfg - cfg = config +class PyQt5PictureMessage(QFrame): - app = QApplication(argv) - p = PyQt5Gui() - return app.exec_() + def __init__(self, message, picture=None): + + super().__init__() + + self._message = message + self._picture = picture + + self.initFrame() + + + def initFrame(self): + + self.setStyleSheet('background-color: black;') + + + def paintEvent(self, event): + + painter = QPainter() + painter.begin(self) + + if self._picture != None: + pix = QPixmap(self._picture).scaled(self.rect().size(), Qt.KeepAspectRatio, Qt.SmoothTransformation) + painter.drawPixmap(pix.rect(), pix, pix.rect()) + + painter.drawText(event.rect(), Qt.AlignCenter, self._message) + painter.end()