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

来源:https://www.cnblogs.com/henjay724/archive/2019/02/21/10416052.html
-Advertisement-
Play Games

wxPython框架雖然成熟穩定,但是相對最近更火的PyQt框架來說,還是顯得古老了一些,控制項風格不符合現代審美觀,因此痞子衡決定學習一下PyQt的用法,感受下PyQt做出來的界面效果到底如何。根據wxPython學習經驗,當然首先要從PyQt的可視化GUI構建工具Qt Designer開始下手,因... ...



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

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

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

一、Qt Designer工具背景

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

  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 模塊。

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

二、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,命令見如下主頁:

  安裝完成之後打開\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"))

三、使用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介紹與入門

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • js String擴展方法 'asdasdasd'.repalceA()"AsdAsdAsd" ...
  • 簡介 處理併發問題的重點不在於你的設計是怎樣的,而在於你要評估你的併發,併在併發範圍內處理。你預估你的併發是多少,然後測試r+m是否支持。緩存的目的是為了應對普通對象資料庫的讀寫限制,依托與nosql的優勢進行高速讀寫。 redis本身也有併發瓶頸。所以你要把讀寫和併發區分開來處理。只讀業務是不是可 ...
  • [TOC] JSON Web Token(縮寫 JWT)是目前最流行的跨域認證解決方案,本文介紹它的原理和用法。 一、跨域認證的問題 互聯網服務離不開用戶認證。一般流程是下麵這樣。 1. 用戶向伺服器發送用戶名和密碼。 2. 伺服器驗證通過後,在當前對話(session)裡面保存相關數據,比如用戶角 ...
  • Python環境的安裝 安裝Python: windows: 1、下載安裝包 https://www.python.org/downloads/ 2、安裝 預設安裝路徑:C:\python27 3、配置環境變數 【右鍵電腦】--》【屬性】--》【高級系統設置】--》【高級】--》【環境變數】--》 ...
  • 前言 開心一刻 一名劫匪慌忙中竄上了一輛車的後座,上車後發現主駕和副駕的一男一女疑惑地回頭看著他,他立即拔出槍威脅到:“趕快開車,甩掉後面的警車,否則老子一槍崩了你!”,於是副駕上的男人轉過臉對那女的說:“大姐,別慌,聽我口令把剛纔的動作再練習一遍,掛一檔,輕鬆離合,輕踩油門,走...走,哎 走.. ...
  • 題意 "題目鏈接" 有$n$個位置,每次你需要以$1 \sim n 1$的一個排列的順序去染每一個顏色,第$i$個數可以把$i$和$i+1$位置染成黑色。一個排列的價值為最早把所有位置都染成黑色的次數。問所有排列的分數之和 Sol 神仙題Orz 不難想到我們可以枚舉染色的次數$i \in [\lce ...
  • 《數據結構》這門課程的安排,就要開始各種演算法和數構的燒腦學習了,從最簡單的應用題型入手吧。 本題要求你寫個程式把給定的符號列印成沙漏的形狀。例如給定17個“*”,要求按下列格式列印 所謂“沙漏形狀”,是指每行輸出奇數個符號;各行符號中心對齊;相鄰兩行符號數差2;符號數先從大到小順序遞減到1,再從小到 ...
  • 在做關於NIO TCP編程小案例時遇到無法監聽write的問題,沒想到只是我的if語句的位置放錯了位置,哎,看了半天沒看出來 貼下課堂筆記: 在Java中使用NIO進行網路TCP套接字編程主要以下幾個類: ServerSocketChannel: 服務端套接字通道,主要監聽接收客戶端請求 Selec ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...