【问题标题】:How to link Qt Designer button to a function in a separate file [duplicate]如何将Qt Designer按钮链接到单独文件中的函数[重复]
【发布时间】:2020-12-04 05:15:06
【问题描述】:

我是 Python 新手,我已经搜索了答案,但找不到(或者说无法正确实现它)。

我在 QtDesigner 的名为“arch.ui”的文件中生成了一个带有几个按钮的窗口,并转换为 arch.py​​。

由于我偶尔会更新 GUI,我不想在 arch.py​​ 中创建函数,所以我为此创建了一个 main.py 文件。

我在将按钮单击链接到函数时遇到问题 => 我尝试将“btnSource”(来自 arch.py​​)链接到函数“printMe”(在 main.py 中)。

显然它不起作用。欢迎任何帮助。

这里是生成的设计器文件:

# Form implementation generated from reading ui file 'arch.ui'
#
# Created by: PyQt5 UI code generator 5.15.0
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(460, 233)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.btnSource = QtWidgets.QPushButton(self.centralwidget)
        self.btnSource.setGeometry(QtCore.QRect(80, 60, 75, 23))
        self.btnSource.setObjectName("btnSource")
        self.lblSource = QtWidgets.QLabel(self.centralwidget)
        self.lblSource.setGeometry(QtCore.QRect(180, 60, 511, 21))
        self.lblSource.setObjectName("lblSource")
        self.lblTarget = QtWidgets.QLabel(self.centralwidget)
        self.lblTarget.setGeometry(QtCore.QRect(180, 120, 481, 16))
        self.lblTarget.setObjectName("lblTarget")
        self.btnTarget = QtWidgets.QPushButton(self.centralwidget)
        self.btnTarget.setGeometry(QtCore.QRect(80, 120, 75, 23))
        self.btnTarget.setObjectName("btnTarget")
        self.btnGo = QtWidgets.QPushButton(self.centralwidget)
        self.btnGo.setGeometry(QtCore.QRect(280, 120, 75, 23))
        self.btnGo.setObjectName("btnGo")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 460, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.btnSource.setText(_translate("MainWindow", "Source"))
        self.lblSource.setText(_translate("MainWindow", "TextLabel"))
        self.lblTarget.setText(_translate("MainWindow", "TextLabel"))
        self.btnTarget.setText(_translate("MainWindow", "Target"))
        self.btnGo.setText(_translate("MainWindow", "Go"))

这是我的 main.py 文件:

from PyQt5 import QtCore, QtGui, QtWidgets
from arch import Ui_MainWindow
import sys 

  
app = QtWidgets.QApplication(sys.argv)
class myWindow(Ui_MainWindow):
    def __init__(self):
        super(myWindow, self).__init__()
        self.btnSource.clicked.connect(self.btnSource.printMe)#

    def printMe(self):
        print('blah blah blah')

MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())

【问题讨论】:

    标签: python pyqt5 qt-designer


    【解决方案1】:

    tl;博士

    子类来自QMainWindow Ui_MainWindow,并从那里调用setupUi;然后创建myWindow的实例:

    class MyWindow(QtWidgets.QMainWindow, Ui_MainWindow):
        def __init__(self):
            super(MyWindow, self).__init__()
            self.setupUi(self)
            self.btnSource.clicked.connect(self.printMe)
    
        def printMe(self):
            print('blah blah blah')
    
    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)
        mainWindow = MyWindow()
        mainWindow.show()
        sys.exit(app.exec_())
    

    说明

    您的代码无法正常工作的原因有很多;虽然主要问题可能是您实际上从未创建了myWindow 的实例(关于这一点,您应该始终为类使用大写名称),使其完全无用,无论如何它都不会起作用.

    那是因为你应该ui类对象继承,而是从你将要使用的QWidget后代(QMainWindow,在你的例子中)继承。

    pyuic 创建的ui_* 对象仅用作高级(且未修改)接口,用于在QWidget 子类的顶部创建 UI。
    调用 setupUi(something) 实际上会为小部件 something 创建所有子小部件,设置布局,可能还有 automatically connects to slots with a compatible name,但仅此而已:事实上,如果您仔细查看 ui 文件中的代码,它实际上什么也没做除了setupUiretranslateUi(也不应该!):甚至没有__init__

    如果您需要添加交互并创建从信号到槽/函数的连接,您应该使用官方指南中关于using Designer with PyQt 中解释的单/多继承方法;唯一的另一种可能性是将loadUi(仍然是基类的子类)与源.ui文件一起使用:

    from PyQt5 import QtWidgets, uic
    
    class MyWindow(QtWidgets.QMainWindow):
        def __init__(self):
            super().__init__()
            uic.loadUi('path/to/gui.ui', self)
            self.someWidget.someSignal.connect(self.someSlot)
            # ...
    
        def someSlot(self, signalArguments, [...]):
            # do something...
    

    PS:由于各种原因,通常最好只在脚本是已运行的脚本时才运行 QApplication(因此是 if __name__ ...),主要是因为应该只有 一个 em> 每个正在运行的程序的 QApplication 实例;在任何情况下,都不应该在类声明之前创建它(除非你真的知道你在做什么);对你来说这没什么大不了的,但是像往常一样,安全总比抱歉好。

    【讨论】:

    • 感谢您提供非常丰富的回复和解释。不幸的是,该解决方案不起作用 -> AttributeError: 'QPushButton' object has no attribute 'printMe'
    • 抱歉,我刚刚从您的代码中复制过来(开头是错误的):它应该指向self.printMe,因为该函数是类实例的成员(self)。
    • 这行得通!。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-07
    • 1970-01-01
    • 1970-01-01
    • 2014-07-25
    • 2013-06-13
    • 1970-01-01
    • 2019-08-29
    相关资源
    最近更新 更多