PyQt5 buttons not connecting(PyQt5按钮未连接)
问题描述
我正在尝试使用 PyQT5 构建一个简单的 GUI,有 3 个按钮用于打开文件浏览器,还有一个按钮用于对所选文件进行处理,但我无法让我的按钮连接到执行此操作所需的功能.
I am trying to build a simple GUI using PyQT5, with 3 buttons to open file browsers and one more to run processing with the selected files, but I can't get my buttons to connect to the functions needed to carry this out.
在 Ctrl
类中,_connect_signals
函数似乎没有调用 _input_select
.谁能帮我弄清楚为什么?
In the Ctrl
class, the _connect_signals
function doesn't seem to be calling _input_select
. Can anyone help me figure out why?
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 教程,但一定是在这个过程中破坏了它.
In case it helps, I started out by butchering this example code from a Real Python tutorial, but must have broken it along the way.
推荐答案
问题是您没有保留对您正在创建的 Ctrl()
实例的任何持久引用.这会导致 python 垃圾在实例创建后立即收集它.
The problem is that you are not keeping any persistent reference to the Ctrl()
instance you are creating. This results in python garbage collecting it as soon as the instance is created.
要解决这个问题,只需将它分配给一个变量:
To solve the issue, just assign it to a variable:
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_())
一些注意事项:
- 虽然将逻辑与接口分离通常是一种很好的做法,但它是一个需要谨慎使用的概念,因为有时它只会使事情变得比应有的复杂.大多数时候(尤其是对于简单的程序),它只会创建更大的代码库而没有带来任何实际好处:它更难阅读和调试,并且您可能最终会不断地从您的逻辑部分和 ui 部分切换代码;
- 您的代码显示了该概念的一个缺点:当您创建文件对话框时,您使用的是
self
,但在这种情况下,它指的是Ctrl
实例,而参数应该是UI
实例(这将导致崩溃,因为 Qt 将获得意外的参数类型);您可以改用self._view
,但是,如前所述,这种情况下的整个分离只会使事情变得不必要地复杂; - 对引用内部对象的字典键使用字符串很少是一个好主意(尤其是在像您这样使用长描述性字符串时);
- 从一个模块中导入多个元素时,通常最好将它们分组而不是使用单行导入:它使代码更整洁,更易于阅读和检查:
from PyQt5.QtWidgets import (QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget, QFileDialog)
- while separating logic from interface is usually good practice, it's a concept that needs to be used with care, as sometimes it only makes things more complex than they should be. Most of the times (especially with simple programs), it only makes a bigger codebase without giving any actual benefit: it's harder to read and to debug, and you'll probably end up continuously switching from the logic parts and the ui parts of your code;
- your code shows one of the drawback of that concept: when you create the file dialog, you're using
self
, but in that case it refers to theCtrl
instance, while the argument should be theUI
instance instead (which will result in a crash, as Qt will get an unexpected argument type); you can useself._view
instead, but, as said, the whole separation in this case just makes things unnecessarily complex; - using strings for dictionary keys that refer to internal objects is rarely a good idea (especially when using long descriptive strings like you did);
- when importing more than one element from a module, it's usually better to group them instead of using single line imports: it makes the code tidier and easier to read and inspect:
from PyQt5.QtWidgets import (QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget, QFileDialog)
这篇关于PyQt5按钮未连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:PyQt5按钮未连接
基础教程推荐
- 用于分类数据的跳跃记号标签 2022-01-01
- 线程时出现 msgbox 错误,GUI 块 2022-01-01
- Python kivy 入口点 inflateRest2 无法定位 libpng16-16.dll 2022-01-01
- 如何让 python 脚本监听来自另一个脚本的输入 2022-01-01
- 使用PyInstaller后在Windows中打开可执行文件时出错 2022-01-01
- Dask.array.套用_沿_轴:由于额外的元素([1]),使用dask.array的每一行作为另一个函数的输入失败 2022-01-01
- 在 Python 中,如果我在一个“with"中返回.块,文件还会关闭吗? 2022-01-01
- 何时使用 os.name、sys.platform 或 platform.system? 2022-01-01
- 筛选NumPy数组 2022-01-01
- 如何在海运重新绘制中自定义标题和y标签 2022-01-01