通过Python解决.ui文件中Pyside Qt小部件的正确方法

Correct way to address Pyside Qt widgets from a .ui file via Python

我已经使用Qt Designer创建了一个GUI,并通过以下方式访问了它

1
2
3
4
5
6
7
8
9
10
11
12
def loadUiWidget(uifilename, parent=None):
    loader = QtUiTools.QUiLoader()
    uifile = QtCore.QFile(uifilename)
    uifile.open(QtCore.QFile.ReadOnly)
    ui = loader.load(uifile, parent)
    uifile.close()
    return ui

MainWindow = loadUiWidget("form.ui")
MainWindow.show()
children = MainWindow.children()
button1 = MainWindow.QPushButton1

" children"已经包含在UI中创建的小部件" QPushButton1"," QTextBrowser1",但是不应由requesive findChildren()方法访问吗?

什么是访问.ui文件小部件的优雅方法?

参考文献:
找到正确的实例,
加载.ui文件


由于Qt Designer中的窗口小部件名称必须唯一,因此层次结构(至少用于获取窗口小部件的引用)是平坦的(没有冲突的风险),因此最好的方法是通过以下方式访问它们:

1
2
3
loader = QtUiTools.QUiLoader()
ui = loader.load('filename.ui', parent)
my_widget = ui.my_widget_name

这将在Qt Designer中的变量my_widget中放置对名为" my_widget_name"的小部件的引用。

我要说的是,以上是访问在加载.ui文件时创建的小部件的最pythonic方式。


在运行时加载UI有两个缺点:

  • 每次运行程序时的开销(实际上,每次使用加载程序时)
  • 缺少对代码完成和检查的支持,因为在加载uifile之前,IDE不知道ui后面的代码。

假设您使用的是PySide的现代版本" Qt for Python",则另一种方法是将.ui文件"编译"为Python类(请参阅docs)。为此,保存filename.ui后,执行

1
pyside2-uic filename.ui -o ui_mainwindow.py

在虚拟环境中(如果有)。新类将称为Ui_MainWindow。假设您的UI中有一个text_box小部件,您现在可以访问其属性和方法。这是一个完整的工作示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import sys
from PySide2.QtWidgets import QApplication, QMainWindow
from ui_mainwindow import Ui_MainWindow


class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.text_box.setPlainText('test')  # here we are addressing widget


if __name__ =="__main__":
    app = QApplication(sys.argv)

    window = MainWindow()
    window.show()

    sys.exit(app.exec_())

笔记:

  • 每次更改.ui文件后,都应调用pyside2-uic。与OP相比,这是此方法的缺点。这也意味着您应该对UI的.ui和.py文件进行版本控制,或者在部署期间以某种方式调用uic。
  • 最大的优势在于,像PyCharm这样的IDE可以访问所有小部件方法和属性,以进行自动补全和代码检查。
  • 到目前为止,pyside2-uic会创建不符合PEP8的代码。但是,只要给窗口小部件提供符合PEP8的名称,您自己的代码就可以了。