Hopefully I am following the guidelines correctly here with my first question. I am trying to create a GUI with the MVC structure. I am having difficulty with understanding why my signals are not always being picked up by the controller. I know that there is just something simple that I'm missing. I'm attaching code from a simple calculator which I used as a guide. I removed most of the features to simplify this as much as possible. It is now only 3 of the original buttons and my own button. For debugging, I just have the value on the button printed out when you press it.
import sys
# Import QApplication and the required widgets from PyQt5.QtWidgets
from PySide2.QtWidgets import QApplication
from PySide2.QtWidgets import QMainWindow
from PySide2.QtWidgets import QWidget
from PySide2.QtCore import Qt
from PySide2.QtWidgets import QGridLayout
from PySide2.QtWidgets import QLineEdit
from PySide2.QtWidgets import QPushButton
from PySide2.QtWidgets import QVBoxLayout
from functools import partial
ERROR_MSG = 'ERROR'
# Create a subclass of QMainWindow to setup the calculator's GUI
class PyCalcUi(QMainWindow):
"""PyCalc's View (GUI)."""
def __init__(self):
"""View initializer."""
super().__init__()
# Set some main window's properties
self.setWindowTitle('PyCalc')
self.setFixedSize(235, 235)
# Set the central widget and the general layout
self.generalLayout = QVBoxLayout()
self._centralWidget = QWidget(self)
self.setCentralWidget(self._centralWidget)
self._centralWidget.setLayout(self.generalLayout)
# Create the display and the buttons
self._createDisplay()
self._createButtons()
def _createDisplay(self):
"""Create the display."""
# Create the display widget
self.display = QLineEdit()
# Set some display's properties
self.display.setFixedHeight(35)
self.display.setAlignment(Qt.AlignRight)
self.display.setReadOnly(True)
# Add the display to the general layout
self.generalLayout.addWidget(self.display)
def _createButtons(self):
"""Create the buttons."""
self.buttons = {}
buttonsLayout = QGridLayout()
# Button text | position on the QGridLayout
buttons = {'7': (0, 0),
'8': (0, 1),
'9': (0, 2),
}
# Create the buttons and add them to the grid layout
for btnText, pos in buttons.items():
self.buttons[btnText] = QPushButton(btnText)
self.buttons[btnText].setFixedSize(40, 40)
buttonsLayout.addWidget(self.buttons[btnText], pos[0], pos[1])
self.mybutton = QPushButton("5")
buttonsLayout.addWidget(self.mybutton,1,0)
# Add buttonsLayout to the general layout
self.generalLayout.addLayout(buttonsLayout)
# Create a Controller class to connect the GUI and the model
class PyCalcCtrl:
"""PyCalc Controller class."""
def __init__(self, model, view):
"""Controller initializer."""
self._evaluate = model
self._view = view
# Connect signals and slots
self._connectSignals()
def _printthis(self):
print("Hi")
def _printthat(self, buttonvalue):
print(buttonvalue)
def _connectSignals(self):
"""Connect signals and slots."""
self._view.mybutton.clicked.connect(self._printthis)
for btnText, btn in self._view.buttons.items():
btn.clicked.connect(partial(self._printthat, btnText))
# Create a Model to handle the calculator's operation
def evaluateExpression(expression):
"""Evaluate an expression."""
try:
result = str(eval(expression, {}, {}))
except Exception:
result = ERROR_MSG
return result
# Client code
def main():
"""Main function."""
# Create an instance of QApplication if it doesn't exist
pycalc = QApplication.instance()
if pycalc is None:
pycalc = QApplication(sys.argv)
# Show the calculator's GUI
view = PyCalcUi()
view.show()
# Create instances of the model and the controller
model = evaluateExpression
PyCalcCtrl(model=model, view=view)
# Execute the calculator's main loop
sys.exit(pycalc.exec_())
if __name__ == '__main__':
main()
This set of code works, BUT if I comment out the
for btnText, btn in self._view.buttons.items():
btn.clicked.connect(partial(self._printthat, btnText))
The self._view.mybutton.clicked.connect(self._printthis)
will no longer work.
What is the btn.clicked.connect(partial(self._printthat, btnText))
line doing which is allowing any other signal I put in def _connectSignals(self): to work. What aspect of that line is achieving something that the mybutton signal isn't doing?
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…