Qt Designer的介绍
在PyQt中编写UI界面可以直接通过代码来实现,也可以通过Qt Designer来完成。Qt Designer的设计符合MVC的架构,其实现了视图和逻辑的分离,从而实现了开发的便捷。Qt Designer中的操作方式十分灵活,其通过拖拽的方式放置控件可以随时查看控件效果。Qt Designer生成的.ui文件(实质上是XML格式的文件)也可以通过pyuic5工具转换成.py文件。
Qt Designer随PyQt5-tools包一起安装,其安装路径在 “Python安装路径\Lib\site-packages\pyqt5-tools”下。
若要启动Qt Designer可以直接到上述目录下,双击designer.exe打开Qt Designer;或将上述路径加入环境变量,在命令行输入designer打开;或在PyCharm中将其配置为外部工具打开。
下面以PyCharm为例,讲述PyCharm中Qt Designer的配置方法。
PyCharm中PyQt5工具配置
打开PyCharm,选择Settings -> Tools -> External Tools,点击左上角的绿色加号。
Name填入QtDesigner(方便后续使用,名称无所谓)。Program选择我们安装的PyQt5-tools下面的designer.exe。Working directory则选择我们的工作目录。然后点击OK,则添加了QtDesigner作为PyCharm的外置工具。
然后添加PyUIC(UI转换工具),PyUIC的Program为Python.exe,在Python的安装目录下面的Scripts目录下,Working directory同理设为我们的工作目录,Arguments则填入如下代码:
1 2 |
-m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py |
最后添加pyrcc用于PyQt5的资源文件转码。具体配置与上述内容相同,Arguments填入:
1 2 |
$FileName$ -o $FileNameWithoutExtension$_rc.py |
退出之前,点击Apply保存配置。配置完成之后,PyCharm中会加入3个工具。
点击QtDesigner则打开QtDesigner的界面。
Qt Designer界面简介
刚打开Qt Designer,则弹出如下图所示的窗口。
创建新的Form给出了5个模板,其中Widget与Main Window最为常用。这里我们选择创建一个Main Window。
上面界面的最左侧菜单为Widget Box,Widget Box中包含PyQt5中的所有Widget组件,我们可以从左侧的Widget Box中拖拽出诸如Button、View和Input等组件到中间的窗口中。
点击Form -> Preview(快捷键为Ctrl+R)则可以预览我们设计好的界面,也可以用Preview In来选择在相应的主题风格下预览。
我们拖拽一个Label与Button进入主窗口(Main Window)。
此时在右上角的Object Inspector(对象查看器)中可以看到主窗口中的已放置的对象(label与pushButton)以及其相应地Qt类。
以Label为例,此时我们点击Main Window中的label或是在Object Inspector中选取label后,查看右侧的一块区域——Property Editor(属性编辑器)。
其主要包含属性有如下:
名称 | 含义 |
---|---|
objectName | 控件对象名称 |
geometry | 相应宽和高与坐标 |
sizePolicy | 控件大小的策略 |
minimumSize | 最小的宽和高 |
maximumSize | 最大的宽和高 |
font | 字体 |
cursor | 光标 |
… | … |
PS:将minimumSize和maximumSize设为一样的数值之后,则窗口的大小固定。
最右下角的部分则为Resource Browser(资源浏览器),资源浏览器中可以添加相应地如图片素材,作为Label或Button等控件的背景图片等。
Qt Designer的UI文件
使用Qt Designer设计保存的文件为.ui格式的文件。
通过保存并使用记事本等软件打开,我们可以看到.ui文件的内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
<span class="php"><span class="hljs-meta"><?</span>xml version=<span class="hljs-string">"1.0"</span> encoding=<span class="hljs-string">"UTF-8"</span><span class="hljs-meta">?></span></span> <span class="hljs-tag"><<span class="hljs-name">ui</span> <span class="hljs-attr">version</span>=<span class="hljs-string">"4.0"</span>></span> <span class="hljs-tag"><<span class="hljs-name">class</span>></span>MainWindow<span class="hljs-tag"></<span class="hljs-name">class</span>></span> <span class="hljs-tag"><<span class="hljs-name">widget</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"QMainWindow"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"MainWindow"</span>></span> <span class="hljs-tag"><<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"geometry"</span>></span> <span class="hljs-tag"><<span class="hljs-name">rect</span>></span> <span class="hljs-tag"><<span class="hljs-name">x</span>></span>0<span class="hljs-tag"></<span class="hljs-name">x</span>></span> <span class="hljs-tag"><<span class="hljs-name">y</span>></span>0<span class="hljs-tag"></<span class="hljs-name">y</span>></span> <span class="hljs-tag"><<span class="hljs-name">width</span>></span>800<span class="hljs-tag"></<span class="hljs-name">width</span>></span> <span class="hljs-tag"><<span class="hljs-name">height</span>></span>600<span class="hljs-tag"></<span class="hljs-name">height</span>></span> <span class="hljs-tag"></<span class="hljs-name">rect</span>></span> <span class="hljs-tag"></<span class="hljs-name">property</span>></span> <span class="hljs-tag"><<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"windowTitle"</span>></span> <span class="hljs-tag"><<span class="hljs-name">string</span>></span>MainWindow<span class="hljs-tag"></<span class="hljs-name">string</span>></span> <span class="hljs-tag"></<span class="hljs-name">property</span>></span> <span class="hljs-tag"><<span class="hljs-name">widget</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"QWidget"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"centralwidget"</span>></span> <span class="hljs-tag"><<span class="hljs-name">widget</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"QLabel"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"label"</span>></span> <span class="hljs-tag"><<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"geometry"</span>></span> <span class="hljs-tag"><<span class="hljs-name">rect</span>></span> <span class="hljs-tag"><<span class="hljs-name">x</span>></span>240<span class="hljs-tag"></<span class="hljs-name">x</span>></span> <span class="hljs-tag"><<span class="hljs-name">y</span>></span>80<span class="hljs-tag"></<span class="hljs-name">y</span>></span> <span class="hljs-tag"><<span class="hljs-name">width</span>></span>72<span class="hljs-tag"></<span class="hljs-name">width</span>></span> <span class="hljs-tag"><<span class="hljs-name">height</span>></span>15<span class="hljs-tag"></<span class="hljs-name">height</span>></span> <span class="hljs-tag"></<span class="hljs-name">rect</span>></span> <span class="hljs-tag"></<span class="hljs-name">property</span>></span> <span class="hljs-tag"><<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"text"</span>></span> <span class="hljs-tag"><<span class="hljs-name">string</span>></span>TextLabel<span class="hljs-tag"></<span class="hljs-name">string</span>></span> <span class="hljs-tag"></<span class="hljs-name">property</span>></span> <span class="hljs-tag"></<span class="hljs-name">widget</span>></span> <span class="hljs-tag"><<span class="hljs-name">widget</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"QPushButton"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"pushButton"</span>></span> <span class="hljs-tag"><<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"geometry"</span>></span> <span class="hljs-tag"><<span class="hljs-name">rect</span>></span> <span class="hljs-tag"><<span class="hljs-name">x</span>></span>240<span class="hljs-tag"></<span class="hljs-name">x</span>></span> <span class="hljs-tag"><<span class="hljs-name">y</span>></span>120<span class="hljs-tag"></<span class="hljs-name">y</span>></span> <span class="hljs-tag"><<span class="hljs-name">width</span>></span>93<span class="hljs-tag"></<span class="hljs-name">width</span>></span> <span class="hljs-tag"><<span class="hljs-name">height</span>></span>28<span class="hljs-tag"></<span class="hljs-name">height</span>></span> <span class="hljs-tag"></<span class="hljs-name">rect</span>></span> <span class="hljs-tag"></<span class="hljs-name">property</span>></span> <span class="hljs-tag"><<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"text"</span>></span> <span class="hljs-tag"><<span class="hljs-name">string</span>></span>PushButton<span class="hljs-tag"></<span class="hljs-name">string</span>></span> <span class="hljs-tag"></<span class="hljs-name">property</span>></span> <span class="hljs-tag"></<span class="hljs-name">widget</span>></span> <span class="hljs-tag"></<span class="hljs-name">widget</span>></span> <span class="hljs-tag"><<span class="hljs-name">widget</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"QMenuBar"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"menubar"</span>></span> <span class="hljs-tag"><<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"geometry"</span>></span> <span class="hljs-tag"><<span class="hljs-name">rect</span>></span> <span class="hljs-tag"><<span class="hljs-name">x</span>></span>0<span class="hljs-tag"></<span class="hljs-name">x</span>></span> <span class="hljs-tag"><<span class="hljs-name">y</span>></span>0<span class="hljs-tag"></<span class="hljs-name">y</span>></span> <span class="hljs-tag"><<span class="hljs-name">width</span>></span>800<span class="hljs-tag"></<span class="hljs-name">width</span>></span> <span class="hljs-tag"><<span class="hljs-name">height</span>></span>26<span class="hljs-tag"></<span class="hljs-name">height</span>></span> <span class="hljs-tag"></<span class="hljs-name">rect</span>></span> <span class="hljs-tag"></<span class="hljs-name">property</span>></span> <span class="hljs-tag"></<span class="hljs-name">widget</span>></span> <span class="hljs-tag"><<span class="hljs-name">widget</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"QStatusBar"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"statusbar"</span>/></span> <span class="hljs-tag"></<span class="hljs-name">widget</span>></span> <span class="hljs-tag"><<span class="hljs-name">resources</span>/></span> <span class="hljs-tag"><<span class="hljs-name">connections</span>/></span> <span class="hljs-tag"></<span class="hljs-name">ui</span>></span> |
从.ui文件的第一行我们便能看出,其实质是一个XML文件。ui文件中存放了在主窗口中的一切控件的相关属性。使用XML文件来存储UI文件,具有高可读性和移植性,因此我们可以方便地将.ui文件转换到.py文件,从而使得我们可以使用Python语言在设计的GUI上面编程。
将.ui文件转换为.py文件
将.ui文件转换到.py文件很简单,在前面我们曾设置了pyuic5这个工具。如果你没有在PyCharm中设置这个工具,或者根本没有使用PyCharm,则可以到命令行中使用如下命令实现.ui到.py的转换。
1 2 |
<span class="hljs-selector-tag">pyuic5</span> <span class="hljs-selector-tag">-</span> <span class="hljs-selector-tag">o</span> 目标文件名<span class="hljs-selector-class">.py</span> 源文件名<span class="hljs-selector-class">.ui</span> |
或者直接在PyCharm中,找到.ui文件,右键 打开菜单找到External Tools->PyUIC。点击之后,我们在相应工程目录下会产生一个.py文件。(注意,.ui文件必须存放在我们的External Tools中设置的相应项目目录下)
转换完成之后,打开.py文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<span class="hljs-comment"># -*- coding: utf-8 -*-</span> <span class="hljs-comment"># Form implementation generated from reading ui file 'mainWindow.ui'</span> <span class="hljs-comment">#</span> <span class="hljs-comment"># Created by: PyQt5 UI code generator 5.10.1</span> <span class="hljs-comment">#</span> <span class="hljs-comment"># WARNING! All changes made in this file will be lost!</span> from PyQt5 import QtCore, QtGui, QtWidgets <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Ui_MainWindow</span>(<span class="hljs-title">object</span>):</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">setupUi</span><span class="hljs-params">(<span class="hljs-keyword">self</span>, MainWindow)</span></span>: MainWindow.setObjectName(<span class="hljs-string">"MainWindow"</span>) MainWindow.resize(<span class="hljs-number">800</span>, <span class="hljs-number">600</span>) <span class="hljs-keyword">self</span>.centralwidget = QtWidgets.QWidget(MainWindow) <span class="hljs-keyword">self</span>.centralwidget.setObjectName(<span class="hljs-string">"centralwidget"</span>) <span class="hljs-keyword">self</span>.label = QtWidgets.QLabel(<span class="hljs-keyword">self</span>.centralwidget) <span class="hljs-keyword">self</span>.label.setGeometry(QtCore.QRect(<span class="hljs-number">240</span>, <span class="hljs-number">80</span>, <span class="hljs-number">72</span>, <span class="hljs-number">15</span>)) <span class="hljs-keyword">self</span>.label.setObjectName(<span class="hljs-string">"label"</span>) <span class="hljs-keyword">self</span>.pushButton = QtWidgets.QPushButton(<span class="hljs-keyword">self</span>.centralwidget) <span class="hljs-keyword">self</span>.pushButton.setGeometry(QtCore.QRect(<span class="hljs-number">240</span>, <span class="hljs-number">120</span>, <span class="hljs-number">93</span>, <span class="hljs-number">28</span>)) <span class="hljs-keyword">self</span>.pushButton.setObjectName(<span class="hljs-string">"pushButton"</span>) MainWindow.setCentralWidget(<span class="hljs-keyword">self</span>.centralwidget) <span class="hljs-keyword">self</span>.menubar = QtWidgets.QMenuBar(MainWindow) <span class="hljs-keyword">self</span>.menubar.setGeometry(QtCore.QRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">800</span>, <span class="hljs-number">26</span>)) <span class="hljs-keyword">self</span>.menubar.setObjectName(<span class="hljs-string">"menubar"</span>) MainWindow.setMenuBar(<span class="hljs-keyword">self</span>.menubar) <span class="hljs-keyword">self</span>.statusbar = QtWidgets.QStatusBar(MainWindow) <span class="hljs-keyword">self</span>.statusbar.setObjectName(<span class="hljs-string">"statusbar"</span>) MainWindow.setStatusBar(<span class="hljs-keyword">self</span>.statusbar) <span class="hljs-keyword">self</span>.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">retranslateUi</span><span class="hljs-params">(<span class="hljs-keyword">self</span>, MainWindow)</span></span>: _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate(<span class="hljs-string">"MainWindow"</span>, <span class="hljs-string">"MainWindow"</span>)) <span class="hljs-keyword">self</span>.label.setText(_translate(<span class="hljs-string">"MainWindow"</span>, <span class="hljs-string">"TextLabel"</span>)) <span class="hljs-keyword">self</span>.pushButton.setText(_translate(<span class="hljs-string">"MainWindow"</span>, <span class="hljs-string">"PushButton"</span>)) |
观察上述文件,可以看到如果不通过Qt Designer来制作界面的话,我们将会一次次地调试程序,来讲按钮和Label等放在合适的位置,这将是极其痛苦的过程。而通过Qt Designer,我们可以快速地制作UI,并生成Python的代码,从而实现快速地UI的开发。
使用转换的.py文件
然而,此时之间运行这个转换好的Python文件是无法显示任何窗口的。因为这个Python文件只有定义主窗口以及其控件的代码,并没有程序入口的代码。为了秉持视图与逻辑分离的原则,我们再编写一个新的脚本来调用这个文件,并且创建一个窗口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<span class="hljs-keyword">import</span> sys <span class="hljs-keyword">from</span> PyQt5.QtWidgets <span class="hljs-keyword">import</span> QApplication, QMainWindow <span class="hljs-keyword">from</span> mainWindow <span class="hljs-keyword">import</span> * <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyWindow</span><span class="hljs-params">(QMainWindow, Ui_MainWindow)</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, parent=None)</span>:</span> super(MyWindow, self).__init__(parent) self.setupUi(self) <span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>: app = QApplication(sys.argv) myWin = MyWindow() myWin.show() sys.exit(app.exec_()) |
通过上述代码,我们继承了Ui_MainWindow类,使用其构造方法构造主窗口,并定义了程序的入口,通过创建QApplication对象来创建Qt窗口。其运行结果如下:
通过上述操作,我们熟悉了Qt Designer设计界面,到实现业务逻辑的大致工作流程。通过这个工作流程可以简化工作,实现速度的提升。
通过对视图与业务逻辑的分离,在每次更改Qt Designer的UI设计的时候,也不用重新编写代码,而只需对更改的部分做稍微的修改即可。
在下一讲中,我们将继续讲解Qt Designer的使用。
作者:养薛定谔的猫
链接:https://www.jianshu.com/p/5b063c5745d0
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。