pythonpyqt信号并不总是有效的

pythonpyqt信号并不总是有效的,python,signals-slots,pyside2,Python,Signals Slots,Pyside2,希望我在这里的第一个问题正确地遵循了指导原则。我正在尝试创建一个具有MVC结构的GUI。我很难理解为什么控制器不总是接收到我的信号。我知道我只是缺少一些简单的东西。我附上了一个简单计算器的代码,我用它作为指南。我删除了大部分功能,以尽可能地简化这个过程。现在只有3个原始按钮和我自己的按钮。为了调试,我只需要在按下按钮时打印出按钮上的值 import sys # Import QApplication and the required widgets from PyQt5.QtWidgets f

希望我在这里的第一个问题正确地遵循了指导原则。我正在尝试创建一个具有MVC结构的GUI。我很难理解为什么控制器不总是接收到我的信号。我知道我只是缺少一些简单的东西。我附上了一个简单计算器的代码,我用它作为指南。我删除了大部分功能,以尽可能地简化这个过程。现在只有3个原始按钮和我自己的按钮。为了调试,我只需要在按下按钮时打印出按钮上的值

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()
这组代码可以工作,但是如果我注释掉

        for btnText, btn in self._view.buttons.items():
            btn.clicked.connect(partial(self._printthat, btnText))
self.\u view.mybutton.clicked.connect(self.\u printthis)
将不再工作


什么是
btn.clicked.connect(部分(self.\u printthat,btnText))
行操作允许我放入def\u connectSignals(self)中的任何其他信号工作。该行的哪个方面实现了mybutton信号没有实现的功能?

问题的原因是PyCalcCtrl对象没有分配给变量,因此它将被销毁,因此无法访问“\u printthis”方法。另一方面,当使用functools.partial时,PyCalcCtrl类的对象被分配到该函数的作用域,这就是它工作的原因

解决方案是将PyCalcCtrl对象分配给一个变量:

ctrl = PyCalcCtrl(model=model, view=view)

ctrl=PyCalcCtrl(model=model,view=view)
谢谢!我现在明白了。