Multiprocessing to separate Photobooth logic and GUI. Pipes to connect them to each other

This commit is contained in:
Balthasar Reuter
2018-03-21 22:09:37 +01:00
parent 65c70f6fc4
commit 0688fa5fa6
2 changed files with 174 additions and 21 deletions

View File

@@ -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)

View File

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