From 5e451feec47dfdf80dffbed011f80a8c51337a43 Mon Sep 17 00:00:00 2001 From: Ben Hoff Date: Sat, 30 Jun 2018 13:37:25 +0000 Subject: [PATCH] started a pyqt mainwindow example --- content/pyqt-mainwindow.rst | 46 ++++++++++++++++++++ scripts/pyqt-mainwindow.py | 83 +++++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 content/pyqt-mainwindow.rst create mode 100644 scripts/pyqt-mainwindow.py diff --git a/content/pyqt-mainwindow.rst b/content/pyqt-mainwindow.rst new file mode 100644 index 0000000..5631679 --- /dev/null +++ b/content/pyqt-mainwindow.rst @@ -0,0 +1,46 @@ +PyQt MainWindow +=============== + +:date: 2018-01-01 01:01 +:category: PyQt +:status: draft +:summary: Setup our Main Window. + +As part of our `PyQt Tutorial series`_, we've added in some `signals and slots`_, and done some basic `layout management`_. Now let's work on our main window a bit. What'd I like is a prompt that shows up everytime we've detected a face. We'll also put in some basic file handeling methods in as well. Ready? + +As a reminder, `here's what our code looks like currently`_. We've got two custom widget, one widget which gives us some basic buttons for controls and houses the main camera, and a reimplemented widget from the ``facerecog`` package which handles the OpenCV logic for us. We've also got a ``main`` function which ties everything together. + +We'll be leveraging our ``face_detected`` signal that we created in the last section of the tutorial. Let's create a big disclaimer that we've detected a face! + +We'll subclass our QMainWindow to make concrete implementations and move some of the code from our ``main`` method into our implementation. + +.. code-block:: python + + from PyQt5 import QtWidgets + + class StatusBar(QtWidgets.QStatusBar): + def __init__(self, parent=None): + super().__init__(parent) + + class MainWindow(QtWidgets.QMainWindow): + def __init__(self, parent=None): + super().__init__(parent) + haar_file = get_haarcascade_filepath() + central_widget = FaceSignalWidget(haar_file) + self.setCentralWidget(central_widget) + +.. image:: http://doc.qt.io/qt-5/images/mainwindowlayout.png + :align: center + +.. code-block:: python + + from PyQt5 import QtWidgets + + class StatusBar(QtWidgets.QStatusBar): + def __init__(self, parent=None): + super().__init__(parent) + + +.. _`PyQt Tutorial series`: {filename}/pyqt-tutorial.rst +.. _`signals and slots`: {filename}/pyqt-signals-slots.rst +.. _`layout management`: {filename}/pyqt-layout-design.rst diff --git a/scripts/pyqt-mainwindow.py b/scripts/pyqt-mainwindow.py new file mode 100644 index 0000000..02ba09a --- /dev/null +++ b/scripts/pyqt-mainwindow.py @@ -0,0 +1,83 @@ +import sys +from PyQt5 import QtCore, QtWidgets + +from facerecog import (RecordVideo, + FaceDetectionWidget, + get_haarcascade_filepath) + + +class FaceRecogControl(QtWidgets.QWidget): + def __init__(self, parent=None): + super().__init__(parent) + haar_filepath = get_haarcascade_filepath() + self.face_detect_widget = FaceDetectionWidget(haar_filepath) + + self.video_recording = RecordVideo() + record_button = QtWidgets.QPushButton('Run') + + layout = Qtwidgets.QVBoxLayout() + layout.addWidget(self.face_detect_widget) + layout.addWidget(record_button) + + self.setLayout(layout) + + # Connect our signal `clicked` to our method `start_recording` + record_button.clicked.connect(self.video_recording.start_recording) + + # alias out the method call `image_data_slot` to make the code + # line shorter + image_data_slot = self.face_detect_widget.image_data_slot + + # connect our signal `image_data` to our method `image_data_slot` + self.video_recording.image_data.connect(image_data_slot) + + +class FaceSignalWidget(FaceDetectionWidget): + face_detected = QtCore.pyqtSignal(str) + + def image_data_slot(self, image_data): + faces = self.detect_faces(image_data) + # If faces our found, `emit` our signal + if faces: + self.face_detected.emit() + + for (x, y, w, h) in faces: + cv2.rectangle(image_data, (x, y), (x+w, y+h), self._red, self._width) + # emit the coordinates, or at least the (x,y), width and height + # self.face_detection_coords.emit(x, y, w, h) + self.face_detected.emit('Detected') + + # NOTE: this code is same as base class ---------------------------- + self.image = self.get_qimage(image_data) + if self.image.size() != self.size(): + self.setFixedSize(self.image.size()) + + self.update() + # ----------------------------------------------------------------- + + +class MainWindow(QtWidgets.QMainWindow): + # FIXME + file_classifier = QtCore.pyqtSignal(str + def __init__(self, parent=None): + super().__init__(parent) + haar_file = get_haarcascade_filepath() + central_widget = FaceSignalWidget(haar_file) + self.setCentralWidget(central_widget) + status_bar = self.statusBar() + central_widget.face_detected.connect(status_bar.showMessage) + + +def main(): + # We need to make the QApplication before our QMainWindow + # We also need to pass in our system argument values (sys.argv) + app = QtWidgets.QApplication(sys.argv) + main_window = MainWindow() + # Show our main window + main_window.show() + # Start the event loop processing + app.exec() + + +if __name__ == '__main__': + main()