如何将Qt Designer按钮链接到单独文件中的函数

时间:2020-08-14 10:02:48

标签: python pyqt5 qt-designer

我是Python的新手,我一直在寻找答案,但是找不到答案(或者无法正确实现它)。

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

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

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

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

此处生成了Designer文件:

# 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_())

1 个答案:

答案 0 :(得分:0)

tl; dr

来自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)。

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

如果您需要添加交互并创建从信号到插槽/功能的连接,则应使用PyQt中关于using Designer的官方指南中所述的单/多继承方法;唯一的其他可能性是对源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__ ...),主要是因为应该只有一个每个运行程序的QApplication实例;无论如何,都不应在类声明之前 创建它(除非您确实知道自己在做什么);对您而言,这并不重要,但与往常一样,安全要比对不起更好。