痞子衡嵌入式:超級好用的可視化PyQt GUI構建工具(Qt Designer)


  你們好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給你們介紹的是PyQt GUI構建工具Qt Designerhtml

  痞子衡開博客至今已有好幾年,一直以嵌入式開發相關主題的文章爲主線,偶爾穿插一些其餘技術或工具的介紹,前段時間由於要作一個跟恩智浦MCU啓動相關的上位機工具 NXP-MCUBootUtility,網上搜索對比了幾個Python下的GUI框架,最終選擇了wxPython這個成熟穩定的GUI庫,從而接觸到wxFormBuilder這個配套wxPython使用的GUI構建工具。苦於網上關於該構建工具的中文資料很少,因此根據本身使用經驗寫了一篇 極易上手的可視化wxPython GUI構建工具(wxFormBuilder),沒想到該篇博客很受歡迎,竟然目前是痞子衡博客裏閱讀量最高的一篇博客,並且也是搜索 wxFormBuilder 關鍵字出來的中文結果排名第二位的連接,真是萬萬沒想到。python

  wxPython框架雖然成熟穩定,可是相對最近更火的PyQt框架來講,仍是顯得古老了一些,控件風格不符合現代審美觀,所以痞子衡決定學習一下PyQt的用法,感覺下PyQt作出來的界面效果到底如何。根據wxPython學習經驗,固然首先要從PyQt的可視化GUI構建工具Qt Designer開始下手,所以便有了本篇博客。git

1、Qt Designer工具背景

  Qt Designer從名字上來看顯然就是久負盛名的跨平臺GUI庫Qt的配套設計工具。Qt庫自己是C++語言實現的;Riverbank公司用Python語言對Qt作了一層封裝,封裝後便成了Python版GUI庫PyQt(目前最新的版本是PyQt5);下面是這兩個GUI庫的官方主頁:github

  Qt的各類UI控件功能均是經過class來實現的,這個連接 https://doc.qt.io/qt-5/classes.html 列出了Qt裏的全部class。PyQt5其用法基本與Qt一致,這個連接 https://www.riverbankcomputing.com/static/Docs/PyQt5/module_index.html#ref-module-index 列出了PyQt5裏全部的Modules,其中用於設計界面最經常使用的即是 QtWidgets 模塊。api

  在Qt官網的Tools下面能夠看到全部Qt相關的工具,在UI design tools下面能夠找到Qt Designer,可見Qt Designer是用於設計GUI界面的工具之一。因爲痞子衡介紹的PyQt5下的GUI構建工具,所以本文的Qt Designer並非直接在Qt官網下載安裝的,具體安裝方法詳見下一章節。app

2、Qt Designer快速上手

  使用Qt Designer去設計GUI界面能夠不用掌握PyQt5裏的各個控件class的具體用法,你只須要在Qt Designer軟件裏添加這些控件便可,下面痞子衡將簡介Qt Designer的用法:框架

2.1軟件安裝

  簡單瞭解PyQt5的module和class即可以開始設計GUI界面,首先得安裝Qt Designer,在安裝完Python3以後(痞子衡安裝的是Python 3.6),藉助\Python36\Scripts\下的pip.exe工具來分別安裝PyQt5和Qt Designer,命令見以下主頁:ide

  安裝完成以後打開\Python36\Lib\site-packages\pyqt5_tools\designer.exe,這即是Qt Designer。函數

2.2軟件界面

  打開Qt Designer可見到以下界面,界面主要分爲四大區:項目區、控件區、編輯區、屬性區。軟件使用起來很是簡單,就是在【控件區】裏點擊添加須要的控件,這些控件的效果會在【編輯區】裏實時顯示,並在【屬性區】這些控件的屬性,【項目區】用於顯示控件間的層級關係。工具

2.3基礎佈局

  讓咱們開始建立一個GUI的基礎框架,基礎框架包括:Container(局部外圍輪廓)、Layout(內部控件區)、menubar(頂部菜單欄)、statusbar(底部狀態欄)。
  第一步是添加一個Container(此處選擇經常使用的Frame),這是GUI的輪廓基礎,有了Frame以後還須要在Frame裏添加Layout(此處選擇豎排樣式),用於規範後續控件的排列樣式。默認GUI即有menubar和statusbar。

2.4多種控件

  基礎佈局搞定以後,接下來即是在Layout裏添加控件,PyQt5支持的控件很是豐富,其中比較經常使用的是以下幾個:各類Button(按鈕)、Label(靜態顯示文本框)、Text Edit(輸入輸出文本框)、Check Box(選中框)、各類Slider(滑動條)等。因爲前面痞子衡選擇的是verticalLayout,所以你會看到控件們都是豎着排的。

2.5控件屬性

  添加了全部控件以後,下一步即是分別設置控件的屬性,進一步調整控件。痞子衡以Push Button屬性爲例,痞子衡勾選了以下3項比較重要的屬性設置,分別是objectName(button在後續python代碼的對象名,通常須要按其功能修改,修改後使得代碼閱讀/修改起來更直觀)、geometry(設置button的尺寸與位置,若是是放在Layout裏,則受限於Layout不可設置)、text(button在GUI裏顯示的標籤名,此處是PushButton,也須要按其功能修改,方便用戶使用軟件)。

2.6保存爲xml代碼(工程文件)

  當GUI界面佈局所有完成以後,需選擇File->Save As保存爲.ui文件,該文件既是Qt Designer的工程文件也是最終生成的GUI xml代碼文件,痞子衡保存在了my_win.ui文件裏。

2.7轉換成python代碼

  雖然保存的my_win.ui文件裏是能夠直接在python代碼裏被加載使用的,可是更好的辦法是直接將.ui文件轉換成相應的.py文件。須要藉助 \Python36\Scripts\pyuic5.exe工具,命令以下:

pyuic5 - o my_win.py my_win.ui

  轉換成功後,讓咱們打開my_win.py文件,能夠簡單看一下這個my_win.py裏的內容,代碼裏首先import了PyQt5相關庫,並定義了名爲Ui_MainWindow的class,這個class主要包含兩個函數setupUi()和retranslateUi()。setupUi()裏初始化了各個控件成員self.xx,這與咱們在Qt Designer裏添加控件是對應的。

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file '.\my_win.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(603, 448)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.frame = QtWidgets.QFrame(self.centralwidget)
        self.frame.setGeometry(QtCore.QRect(100, 80, 361, 211))
        self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame.setObjectName("frame")
        self.verticalLayoutWidget = QtWidgets.QWidget(self.frame)
        self.verticalLayoutWidget.setGeometry(QtCore.QRect(30, 20, 160, 172))
        self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout.setObjectName("verticalLayout")
        self.pushButton = QtWidgets.QPushButton(self.verticalLayoutWidget)
        self.pushButton.setEnabled(True)
        self.pushButton.setObjectName("pushButton")
        self.verticalLayout.addWidget(self.pushButton)
        self.label = QtWidgets.QLabel(self.verticalLayoutWidget)
        self.label.setObjectName("label")
        self.verticalLayout.addWidget(self.label)
        self.textEdit = QtWidgets.QTextEdit(self.verticalLayoutWidget)
        self.textEdit.setObjectName("textEdit")
        self.verticalLayout.addWidget(self.textEdit)
        self.checkBox = QtWidgets.QCheckBox(self.verticalLayoutWidget)
        self.checkBox.setObjectName("checkBox")
        self.verticalLayout.addWidget(self.checkBox)
        self.horizontalSlider = QtWidgets.QSlider(self.verticalLayoutWidget)
        self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal)
        self.horizontalSlider.setObjectName("horizontalSlider")
        self.verticalLayout.addWidget(self.horizontalSlider)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 603, 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.pushButton.setText(_translate("MainWindow", "PushButton"))
        self.label.setText(_translate("MainWindow", "TextLabel"))
        self.checkBox.setText(_translate("MainWindow", "CheckBox"))

3、使用Qt Designer生成的代碼

  前面已經使用Qt Designer生成GUI界面類Ui_MainWindow並保存在my_win.py文件中,此時須要建立一個主函數文件去調用Ui_MainWindow,下面是痞子衡建立的main_win.py中的代碼:

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
# 導入my_win.py中內容
from my_win import *

# 建立mainWin類並傳入Ui_MainWindow
class mainWin(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(mainWin, self).__init__(parent)
        self.setupUi(self)

if __name__ == '__main__':
    # 下面是使用PyQt5的固定用法
    app = QApplication(sys.argv)
    main_win = mainWin()
    main_win.show()
    sys.exit(app.exec_())

3.1觸發事件與響應

  有了Button,咱們確定但願其能與一個響應函數相聯繫起來,此處痞子衡定義了showMessage()函數,而且將showMessage()與PushButton綁定起來,點擊Button便會執行一次這個showMessage()函數。代碼以下:

class mainWin(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(mainWin, self).__init__(parent)
        self.setupUi(self)
        # 將響應函數綁定到指定Button
        self.pushButton.clicked.connect(self.showMessage)

    # Button響應函數
    def showMessage(self):
        self.textEdit.setText('hello world')

  最後讓咱們測試一下這個GUI軟件,在命令行下運行main_win.py

PS D:\my_git_repo\> python .\main_win.py

  至此,PyQt5 GUI構建工具Qt Designer痞子衡便介紹完畢了,掌聲在哪裏~~~

參考資料

  1. 使用PyQt來編寫第一個Python GUI程序
  2. PyQT5速成教程-2 Qt Designer介紹與入門
相關文章
相關標籤/搜索