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 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- 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): def main(argv):
config = Config.Config('photobooth.cfg') config = Config('photobooth.cfg')
return PyQt5Gui.run(argv, config)
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 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- 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.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): def __init__(self):
@@ -13,6 +65,21 @@ class PyQt5Gui(QMainWindow):
self.initUI() 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): def initUI(self):
global cfg global cfg
@@ -40,24 +107,35 @@ class PyQt5Gui(QMainWindow):
self.setCentralWidget(content) 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): def closeEvent(self, e):
reply = QMessageBox.question(self, 'Confirmation', "Quit Photobooth?", reply = QMessageBox.question(self, 'Confirmation', "Quit Photobooth?",
QMessageBox.Yes | QMessageBox.No, QMessageBox.No) QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes: if reply == QMessageBox.Yes:
self.transport.close()
e.accept() e.accept()
else: else:
e.ignore() e.ignore()
def keyPressEvent(self, e): def keyPressEvent(self, event):
pass
# if self.photobooth.status == Status.idle: if event.key() == Qt.Key_Escape:
# if e.key() == Qt.Key_Escape: self.showStart()
# self.showStart() elif event.key() == Qt.Key_Space:
# elif e.key() == Qt.Key_Space: self.transport.send('triggered')
# self.centralWidget().trigger()
@@ -66,7 +144,7 @@ class PyQt5Start(QFrame):
def __init__(self, parent): def __init__(self, parent):
super().__init__(parent) super().__init__()
self.initFrame(parent) self.initFrame(parent)
@@ -79,7 +157,7 @@ class PyQt5Start(QFrame):
btnStart = QPushButton('Start Photobooth') btnStart = QPushButton('Start Photobooth')
btnStart.resize(btnStart.sizeHint()) btnStart.resize(btnStart.sizeHint())
# btnStart.clicked.connect(parent.showPhotobooth) btnStart.clicked.connect(parent.showIdle)
grid.addWidget(btnStart, 0, 0) grid.addWidget(btnStart, 0, 0)
btnSettings = QPushButton('Settings') btnSettings = QPushButton('Settings')
@@ -98,7 +176,7 @@ class PyQt5Settings(QFrame):
def __init__(self, parent): def __init__(self, parent):
super().__init__(parent) super().__init__()
self._parent = parent self._parent = parent
self.initFrame() self.initFrame()
@@ -247,11 +325,32 @@ class PyQt5Settings(QFrame):
self._parent.showSettings() self._parent.showSettings()
def run(argv, config):
global cfg class PyQt5PictureMessage(QFrame):
cfg = config
app = QApplication(argv) def __init__(self, message, picture=None):
p = PyQt5Gui()
return app.exec_() 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()