Receiving a signal from the viewΒΆ
In the Add Button 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:
from qtpy import QtWidgets, QtCore, QtGui
class View(QtWidgets.QWidget):
doSomethingSignal = QtCore.Signal()
def __init__(self, parent=None):
super().__init__(parent)
self.button = QtWidgets.QPushButton('Hi', self)
self.button.setStyleSheet("background-color:lightgrey")
# connect button to signal
self.button.clicked.connect(self.btn_click)
self.label = QtWidgets.QLabel()
self.label.setText("Button")
# add widgets to layout
self.sub_layout = QtWidgets.QHBoxLayout()
self.sub_layout.addWidget(self.label)
self.sub_layout.addWidget(self.button)
grid = QtWidgets.QVBoxLayout(self)
grid.addLayout(self.sub_layout)
# set the layout for the view widget
self.setLayout(grid)
#send signals
def btn_click(self):
print ("hellow from view")
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
).
class Presenter(object):
# pass the view and model into the presenter
def __init__(self, view):
self.view = view
self.view.doSomethingSignal.connect(self.handleButton)
# handle signals
def handleButton(self):
print("hello world, from the presenter")
The main is now:
from qtpy import QtWidgets, QtCore, QtGui
import sys
import view
import presenter
"""
A wrapper class for setting the main window
"""
class Demo(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.window = QtWidgets.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")
def get_qapplication_instance():
if QtWidgets.QApplication.instance():
app = QtWidgets.QApplication.instance()
else:
app = QtWidgets.QApplication(sys.argv)
return app
app = get_qapplication_instance()
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.