Newer
Older
.. _ReceivingSignalFromView:
================================
Receiving a signal from the view
================================
In the :ref:`Add Button <AddButton>` section we had the response to a button press
within the View. In practice this is not a good implementation. If the
response was more complicated then it would be difficult to maintain
the View as it would become extremely long. Furthermore creating the
look of the GUI is fairly simple and any logic/responses should be
contained within the Presenter.
In this section we will make a simple Presenter for when a button is
pressed. First we will start with the View:
.. code-block:: python
from __future__ import (absolute_import, division, print_function)
import PyQt4.QtGui as QtGui
import PyQt4.QtCore as QtCore
class view(QtGui.QWidget):
doSomethingSignal = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(view, self).__init__(parent)
self.button = QtGui.QPushButton('Hi', self)
self.button.setStyleSheet("background-color:lightgrey")
# connect button to signal
self.button.clicked.connect(self.btn_click)
self.label = QtGui.QLabel()
self.label.setText("Button")
# add widgets to layout
self.sub_layout = QtGui.QHBoxLayout()
self.sub_layout.addWidget(self.label)
self.sub_layout.addWidget(self.button)
grid = QtGui.QVBoxLayout(self)
grid.addLayout(self.sub_layout)
# set the layout for the view widget
self.setLayout(grid)
#send signals
def btn_click(self):
self.doSomethingSignal.emit()
The above code has two new additions. The first is the creation of a
custom signal on line eight. It is also possible to pass objects with
the signals. The second addition is that ``btn_click`` now emits the
custom signal and will be caught by the Presenter.
The Presenter is initialised with the View and must be a member of the
Presenter class. It is therefore possible to change the View by
passing a different one to the presenter. For example you may want to
have the widgets in a grid or in a table. The Presenter connects the
custom signal from the View to its own function (``handleButton``).
.. code-block:: python
from __future__ import (absolute_import, division, print_function)
class Presenter(object):
# pass the view and model into the presenter
def __init__(self, view):
self.view.doSomethingSignal.connect(self.handleButton)
# handle signals
def handleButton(self):
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
print("hello world, from the presenter")
The main is now:
.. code-block:: python
from __future__ import (absolute_import, division, print_function)
import PyQt4.QtGui as QtGui
import PyQt4.QtCore as QtCore
import sys
import view
import presenter
"""
A wrapper class for setting the main window
"""
class demo(QtGui.QMainWindow):
def __init__(self, parent=None):
super(demo, self).__init__(parent)
self.window = QtGui.QMainWindow()
my_view = view.view(self)
self.my_presenter = presenter.Presenter(my_view)
# set the view for the main window
self.setCentralWidget(my_view)
self.setWindowTitle("view tutorial")
if QtGui.QApplication.instance():
_app = QtGui.QApplication.instance()
else:
_app = QtGui.QApplication(sys.argv)
return _app
app = qapp()
window = demo()
window.show()
app.exec_()
The View and Presenter are both created, but only the Presenter has to
be a member of the demo class. The View is created to be passed to the
Presenter and the View could easily be replaced.