Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev Branch of MainWindow Example #33

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions content/pyqt-mainwindow.rst
Original file line number Diff line number Diff line change
@@ -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
83 changes: 83 additions & 0 deletions scripts/pyqt-mainwindow.py
Original file line number Diff line number Diff line change
@@ -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()