Python PyQt5按钮未连接

Python PyQt5按钮未连接,python,pyqt5,Python,Pyqt5,我正在尝试使用PyQT5构建一个简单的GUI,有3个按钮打开文件浏览器,还有一个按钮运行对所选文件的处理,但我无法让我的按钮连接到执行此操作所需的功能 在Ctrl类中,\u connect\u signals函数似乎没有调用\u input\u select。有人能帮我找出原因吗 import sys # Import QApplication and the required widgets from PyQt5.QtWidgets from PyQt5.QtWidgets import Q

我正在尝试使用PyQT5构建一个简单的GUI,有3个按钮打开文件浏览器,还有一个按钮运行对所选文件的处理,但我无法让我的按钮连接到执行此操作所需的功能

Ctrl
类中,
\u connect\u signals
函数似乎没有调用
\u input\u select
。有人能帮我找出原因吗

import sys

# Import QApplication and the required widgets from PyQt5.QtWidgets
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QFileDialog


# Create a subclass of QMainWindow to setup the calculator's GUI
class UI(QMainWindow):
    """App's View (GUI)."""

    def __init__(self):
        """View initializer."""
        super().__init__()
        # Set some main window's properties
        self.setFixedSize(300, 150)
        # 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 buttons
        self._create_buttons()

    def _create_buttons(self):
        """Create the buttons."""
        self.buttons = {}
        buttons_layout = QVBoxLayout()
        # Button text | position on the QVBoxLayout
        buttons = {
            "Select input file...": 0,
            "Select config file...": 1,
            "Select output file...": 2,
            "Run": 3,
        }
        # Create the buttons and add them to the grid layout
        for btnText, pos in buttons.items():
            self.buttons[btnText] = QPushButton(btnText)
            buttons_layout.addWidget(self.buttons[btnText], pos)
        # Add buttons_layout to the general layout
        self.generalLayout.addLayout(buttons_layout)


# Create a Controller class to connect the GUI and the model
class Ctrl:
    """App's Controller."""

    def __init__(self, setup, view):
        """Controller initializer."""
        self._view = view
        self._setup = setup
        # Connect signals and slots
        self._connect_signals()

    def _input_select(self):    # Not being called
        print("input selection")

        options = QFileDialog.Options()
        file_select, _ = QFileDialog.getOpenFileNames(
            self,
            'Select Input File...',
            '',
            'CSV Files (*.csv);;All Files (*)',
            options=options
        )
        if file_select:
            self._setup["input"] = file_select

    def _connect_signals(self):
        """Connect signals and slots."""
        self._view.buttons["Select input file..."].clicked.connect(self._input_select)  # Not working!


# Client code
def main():
    """Main function."""
    # Create an instance of `QApplication`
    app = QApplication(sys.argv)
    # Show the app's GUI
    view = UI()
    view.show()
    setup = {}
    # Create instance of the controller
    Ctrl(setup=setup, view=view)
    # Execute app's main loop
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()


如果有帮助的话,我从一个真正的Python教程开始,但一定是一路中断了它。

问题是您没有保留对正在创建的
Ctrl()
实例的任何持久引用。这会导致python在创建实例后立即对其进行垃圾收集

要解决此问题,只需将其分配给变量:

def main():
    """Main function."""
    # Create an instance of `QApplication`
    app = QApplication(sys.argv)
    # Show the app's GUI
    view = UI()
    view.show()
    setup = {}
    # Create instance of the controller
    ctrl = Ctrl(setup=setup, view=view)
    # Execute app's main loop
    sys.exit(app.exec_())
def main():
“”“主要功能。”“”
#创建“QApplication”的实例`
app=QApplication(sys.argv)
#显示应用程序的GUI
视图=用户界面()
view.show()
设置={}
#创建控制器的实例
ctrl=ctrl(设置=设置,视图=视图)
#执行应用程序的主循环
sys.exit(app.exec_())
一些考虑:

  • 虽然将逻辑和接口分离通常是一个好的实践,但这是一个需要小心使用的概念,因为有时它只会使事情变得比应该的更复杂。大多数情况下(特别是对于简单的程序),它只会生成更大的代码库,而不会带来任何实际的好处:更难阅读和调试,并且最终可能会不断地从代码的逻辑部分和ui部分切换
  • 您的代码显示了该概念的一个缺点:当您创建文件对话框时,您使用的是
    self
    ,但在这种情况下,它指的是
    Ctrl
    实例,而参数应该是
    UI
    实例(这将导致崩溃,因为Qt将获得意外的参数类型);你可以用self.\u view来代替,但是,正如前面所说的,在这种情况下,整个分离只会使事情变得不必要的复杂
  • 对引用内部对象的字典键使用字符串很少是个好主意(尤其是像您这样使用长描述性字符串时)
  • 当从一个模块导入多个元素时,通常最好将它们分组,而不是使用单行导入:这样可以使代码更整洁,更易于阅读和检查:
    来自PyQt5.qtwidts导入(QApplication、QMainWindow、QPushButton、QVBoxLayout、QWidget、QFileDialog)

回答得很好,谢谢!赋值给一个变量作为一个即时的解决方案效果很好,我很感激关于最佳实践的建议。