一.PyQt5簡介
PyQt5是一個用於建立圖形使用者介面(GUI)應用程式的跨平臺工具集,它將Qt庫(廣泛用於C++程式語言中建立豐富的GUI應用程式)的功能包裝給Python使用者。PyQt5是由Riverbank Computing開發的,並且可以在所有主流作業系統上執行,包含Windows、macOS和Linux。
PyQt5包括了超過620個類和6000個函式和方法。這個框架支援包括SQL資料庫、執行緒、Unicode、正規表示式、網路程式設計等高階功能。除了GUI功能外,PyQt5還允許使用者訪問Qt的模型/檢視架構和QML(Qt Modeling Language),這是一種專門為建立動態和自定義使用者介面而設計的語言。
二.環境搭建
1.終端使用pip安裝PyQt5庫
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple PyQt5
2.如果出現Could not build wheels for PyQt5_sip, which is required to install pyproject.toml-based projects報錯資訊
3.先安裝 Visual Studio 後再安裝PyQt5即可,終端執行如下指令
wget https://aka.ms/vs/17/release/vs_BuildTools.exe -o vs_BuildTools.exe ; cmd /c vs_BuildTools.exe
勾選C++/CLI後安裝就行
三.基本用法
1.PyQt5常見的模組
QApplication | 這個類管理GUI應用程式的控制流和主要設定,並且是每個PyQt5應用程式中必須有的部分 |
QWidget | 所有使用者介面物件的基類。當你想建立一個自定義的視窗時,你會使用或者繼承這個類 |
QLabel | 用於展示文字或圖片的類 |
QtCore | 其他模組使用的核心非 GUI 類 |
QAction | 用於處理選單欄、工具欄或快捷鍵等的動作。 |
QtSql | 使用 SQL 進行資料庫整合的類 |
QtXml | 處理 XML 的類 |
QSlider | 滑動條,讓使用者透過滑動選擇一個數值。 |
2.一個簡單的視窗建立
import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import QWidget, QLabel, QMessageBox, QApplication def windows(): # 建立一個 QApplication 類的應用程式物件 app = QApplication(sys.argv) # 基於QWidget類宣告視窗 w = QWidget() # 新增一個QLabel物件,並將標籤新增“helloworld”文字。 b = QLabel(w) b.setText("Hello World!") # 設定文字控制元件在視窗中的位置(x,y) b.move(50, 50) # 設定label控制元件的長和寬 b.resize(100,20) # 設定字型樣式大小 font = QFont() font.setFamily("Arial") # 字型樣式,中文英文都可(“楷體”) font.setPointSize(20) # 字型大小 b.setFont(font) # 透過 setGeometry() 方法定義視窗的大小和位置(x,y,w,h) w.setGeometry(100, 100, 500, 1000) # 設定視窗標題 w.setWindowTitle("PyQt5") # 顯示視窗 w.show() # 進入應用程式的主迴圈app.exec_()方法(視窗一直顯示) sys.exit(app.exec_()) if __name__ == '__main__': windows()
備註寫的很詳細了,這裡就不一一介紹每行程式碼的意思了。
3.視窗icon設定
import sys from PyQt5.QtGui import * from PyQt5.QtWidgets import QWidget, QApplication # 匯入儘量用具體類,不用* class Window(QWidget): def __init__(self, parent=None): super().__init__(parent) self.initUI() self.setGeometry(100, 100, 500, 500) self.setWindowTitle("PyQt5") # 設定icon def initUI(self): self.setWindowIcon(QIcon('./2.jpg')) # 設定視窗左上角icon def main(): app = QApplication(sys.argv) ex = Window() ex.show() sys.exit(app.exec_()) if __name__ == '__main__': main()
上述程式碼中,我們在initUI函式中,呼叫父類setWindowIcon()方法去設定視窗icon,在Window類中初始化時去呼叫initUI函式來實現設定icon。
4.QLabel控制元件
def qlabel(self): font = QFont() font.setFamily("Arial") font.setPointSize(16) label = QLabel(self) label.setText("Hello World") # 設定文字 label.setFont(font) # 設定文字字型型別及大小 label.move(50, 20) # 控制元件在視窗的位置
這裡和如上寫法一致,在Window類中寫一個qlabel函式,裡面去呼叫QLabel,再在Window類中初始化時呼叫這個函式即可(使用QLabel模組時需提前匯入該模組),我們來看下結果。
5.tips資訊提示框
def tips(self): # 建立一個按鈕控制元件 btn = QPushButton('Button', self) # 設定文字字型及大小 btn.setFont(QFont('SansSerif', 50)) # 設定tips btn.setToolTip('This is a widget') # 設定按鈕在視窗的位置 btn.move(100, 100)
效果如下,滑鼠懸浮在button上時,會出現tips資訊彈框。
6.關閉二次確定彈框
主動關閉視窗(即點選視窗右上角X),彈出二次確定彈框,提示是否關閉。
import sys from PyQt5.QtGui import * from PyQt5.QtWidgets import QWidget, QApplication, QMessageBox, QDesktopWidget # 匯入儘量用具體類,不用* class Window(QWidget): def __init__(self, parent=None): super().__init__(parent) self.initUI() self.setGeometry(100, 100, 500, 500) self.setWindowTitle("PyQt5") self.center() # 設定icon def initUI(self): self.setWindowIcon(QIcon('./2.jpg')) def closeEvent(self, event): # 關閉二次確定彈框 reply = QMessageBox.question(self, '是否關閉', "Are you sure to quit?", QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: event.accept() # 關閉視窗 else: event.ignore() # 不關閉 def center(self): # 設定視窗居中 qt = self.frameGeometry() # 獲取需要操作的視窗位置,長寬(即設定的setGeometry) cp = QDesktopWidget().availableGeometry().center() # 獲取電腦解析度 qt.moveCenter(cp) # 獲取電腦中間位置 self.move(qt.topLeft()) # 將視窗移動到中間位置 def main(): app = QApplication(sys.argv) ex = Window() ex.show() sys.exit(app.exec_()) if __name__ == '__main__': main()
上述程式碼中重寫了父類中的closeEvent方法,透過QMessageBox.question()來獲取使用者行為,event.accept()來確定關閉視窗。
7.關閉視窗事件
def clos(self): qbtn = QPushButton('Quit', self) # 建立一個按鈕 qbtn.clicked.connect(QCoreApplication.instance().quit) # 回撥關閉事件 qbtn.setToolTip("點選關閉視窗") # tips提示 qbtn.move(0, 0)
如下圖效果,滑鼠點選Quit按鈕後視窗關閉,其效果和關閉按鈕X一致。
8.選單欄和工具欄
QMainWindow
用於建立主應用程式視窗的類。它是 QWidget
的一個子類,提供了建立具有選單欄、工具欄、狀態列等的主視窗所需的功能。
1)狀態列
import sys from PyQt5.QtWidgets import QMainWindow, QApplication class Example(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setGeometry(100, 100, 500, 500) self.setWindowTitle('Statusbar') self.statusBar().showMessage("狀態列") # 設定狀態列 if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() ex.show() sys.exit(app.exec_())
狀態列的設定很簡單,透過呼叫QMainWindow的statusBar()方法建立狀態列,showMessage()來設定狀態列顯示的文字。
2)選單欄
def bar(self): action = QAction(QIcon('./2.jpg'), '登入', self) # 建立QAction例項 action.setShortcut('Ctrl+a') # 設定快捷鍵操作 action.setStatusTip('登入') # 狀態列提示,視窗的左下角出現,滑鼠懸停在選項上會出現 action.triggered.connect(qApp.quit) # 點選事件後回撥的方法(qApp.quit關閉視窗) menubar = self.menuBar() # 建立一個選單欄 menu = menubar.addMenu('File') # 設定選單欄tab menu.addAction(action) # 關聯事件
用過menuBar()建立一個選單欄,並新增addMenu()tab項,透過addAction()新增QAction行為動作,具體效果如下。
triggered.connect(qApp.quit)設定了觸發動作後回撥事件,即點選登入選項或快捷鍵Ctrl+A時會觸發qApp.quit關閉視窗。上訴中我們只建立了一個選單欄並只繫結了一個QAction如果想要多個選單欄多個動作,可以建立多個addMenu(),下面看下具體例項。
def bar(self): action = QAction(QIcon('./2.jpg'), '登入', self) # 建立QAction例項 action.setShortcut('Ctrl+a') # 設定快捷鍵操作 action.setStatusTip('登入') # 狀態列提示,視窗的左下角出現,滑鼠懸停在選項上會出現 action.triggered.connect(qApp.quit) # 點選事件後回撥的方法(qApp.quit關閉視窗) action1 = QAction(QIcon('./2.jpg'), '登入', self) # 建立QAction例項 action1.setShortcut('Ctrl+a') # 設定快捷鍵操作 action1.setStatusTip('退出') # 狀態列提示,視窗的左下角出現,滑鼠懸停在選項上會出現 action1.triggered.connect(qApp.quit) # 點選事件後回撥的方法(qApp.quit關閉視窗) menubar = self.menuBar() # 建立一個選單欄 menu = menubar.addMenu('File') # 設定選單欄tab menubar1 = self.menuBar() # 建立一個選單欄 menu1 = menubar1.addMenu('File1') # 設定選單欄tab menu.addAction(action) # 關聯事件 menu.addAction(action1) # 關聯事件
3)子選單欄
上面我們只是實現了一級選單欄,那麼在需求中要求建立二級,三級或者多級選單,此時就需要用到QMenu()來建立下拉選單欄了,我們先來看下二級選單欄的建立。
# 建立子選單 def bar_z(self): menubar = self.menuBar() # 建立選單欄 menu = menubar.addMenu('File') # 設定選單欄tab newmenu = QMenu('一級下拉框', self) # 建立一個下拉選單 impAct = QAction('二級目錄', self) # 設定一個動作 impAct.triggered.connect(self.btn) # 點選事件後回撥的方法 newmenu.addAction(impAct) # 新增動作到下選單中 newact = QAction('一級目錄', self) # 建立動作 menu.addAction(newact) # 新增動作到選單欄 menu.addMenu(newmenu) # 新增下拉選單到選單欄 def btn(self): # 建立一個按鈕控制元件 btn = QPushButton('Button', self) # btn.setGeometry(100, 100, 80, 30) btn.move(100, 100) btn.setToolTip("button") btn.show()
如果我們想建立三級目錄甚至更多級的目錄,可以建立多個下拉選單欄,並透過addMenu()新增進去,下面看下具體實現。
# 建立子選單 def bar_z(self): menubar = self.menuBar() # 建立選單欄 menu = menubar.addMenu('File') # 設定選單欄tab newmenu1 = QMenu('二級下拉框', self) # 建立一個下拉選單 impAct1 = QAction('三級目錄', self) # 設定一個動作 impAct1.triggered.connect(self.btn) # 點選事件後回撥的方法 newmenu1.addAction(impAct1) # 新增動作到下選單中 newmenu = QMenu('一級下拉框', self) # 建立一個下拉選單 impAct = QAction('二級目錄', self) # 設定一個動作 impAct.triggered.connect(self.btn) # 點選事件後回撥的方法 newmenu.addAction(impAct) # 新增動作到下選單中 newmenu.addMenu(newmenu1) # 新增下拉選單欄到二級選單下 newact = QAction('一級目錄', self) # 建立動作 menu.addAction(newact) # 新增動作到選單欄 menu.addMenu(newmenu) # 新增下拉選單到選單欄
4)帶核取方塊的選單
def bar_checkable(self): menubar = self.menuBar() bar_menu = menubar.addMenu('View') # 新增選單欄 statact = QAction('核取方塊', self, checkable=True) # 建立一個可以勾選的動作 statact.setStatusTip('View statusbar') statact.setChecked(True) # 設定預設選中 statact.triggered.connect(self.menu) bar_menu.addAction(statact) def menu(self, state): if state: print("勾選後執行的事件") # 勾選了 else: print("取消勾選執行的事件") # 取消勾選
QAction()中,checkable=True表示可以勾選的動作。
5)右鍵欄
滑鼠懸浮再視窗上,右擊開啟的選單欄,此功能需要重寫父類中contextMenuEvent()方法,看下程式碼演示。
def contextMenuEvent(self, event): rightmenu = QMenu(self) # 建立一個下拉選單 # 新增動作 d = rightmenu.addAction("列印") q = rightmenu.addAction("退出") ture = rightmenu.addAction("確定") action = rightmenu.exec_(self.mapToGlobal(event.pos())) # exec_()顯示選單。獲取動作行為 if action == d: self.btn() elif action == q: qApp.quit() # 關閉視窗 else: print("無確定內容")
6)工具欄
工具欄可以理解為是多個動作的集合,可以將多個QAction()新增展示出來。
def bar_tool(self): # 多個動作集合 action = QAction("工具1",self) action2 = QAction("工具2",self) action.setStatusTip("點選退出") action.triggered.connect(qApp.quit) toolbat = self.addToolBar("工具欄") # 建立一個工具欄 toolbat.addAction(action) # 將動作新增到工具欄 toolbat.addAction(action2) # 將動作新增到工具欄
7)主視窗顯示
這個就不做過多介紹,在初始__init__中呼叫上訴幾種方法即可,預設選單欄在最頂部,新增的動作會更加呼叫的先後從左到右排列,工具欄預設在選單欄下發,這裡只看下效果截圖。
9.頁面佈局
1)座標佈局
import sys from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QLabel, QApplication, QWidget class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setGeometry(100, 100, 500, 500) self.setWindowTitle('Statusbar') q1 = QLabel("quit", self) q2 = QLabel("quit2", self) q3 = QLabel("quit3", self) q1.move(20, 20) # 座標佈局 q2.move(20, 80) # 座標佈局 q3.move(20, 140) # 座標佈局 if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() ex.show() sys.exit(app.exec_())
上述中透過move(x, y)方法來設定qlable的位置
2)介面比例佈局
import sys from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QApplication, QPushButton, QHBoxLayout, QWidget class Example(QWidget): def __init__(self): super().__init__() self.initUI() self.button() def initUI(self): self.setGeometry(100, 100, 500, 500) self.setWindowTitle('Statusbar') def button(self): # 比例佈局 ok = QPushButton("ok") # 建立三個按鈕 cancel = QPushButton("cancel") cancel1 = QPushButton("cancel1") hbox1 = QHBoxLayout() # 建立一個水平佈局 hbox1.addWidget(ok) # 新增按鈕到水平佈局中 hbox1.addStretch(1) # 設定水平比例間距 hbox1.addWidget(cancel) # 新增按鈕到水平佈局中 hbox1.addStretch(1) # 設定水平比例間距 hbox1.addWidget(cancel1) hbox1.addStretch(6) self.setLayout(hbox1) # 新增到佈局器 if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() ex.show() sys.exit(app.exec_())
import sys from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QApplication, QPushButton, QHBoxLayout, QVBoxLayout, QWidget class Example(QWidget): def __init__(self): super().__init__() self.initUI() self.button() def initUI(self): self.setGeometry(100, 100, 500, 500) self.setWindowTitle('Statusbar') def button(self): # 比例佈局 ok = QPushButton("ok") # 建立三個按鈕 cancel = QPushButton("cancel") cancel1 = QPushButton("cancel1") hbox = QHBoxLayout() # 建立一個水平佈局 hbox.addStretch(1) # 設定水平比例間距(只設定一個stretch,會將按鈕擠到最右側。若stretch寫在addWidget下面,則按鈕會被寄到最左側) hbox.addWidget(ok) # 新增按鈕到水平佈局中 hbox.addWidget(cancel) vbox = QVBoxLayout() # 建立一個垂直佈局 vbox.addStretch(1) # 設定垂直比例間距(只設定一個stretch,會將按鈕擠到最下面。若stretch寫在addlayout下面,則按鈕會被寄到最下面) vbox.addLayout(hbox) # 將剛剛建立的水平佈局新增到垂直佈局中 self.setLayout(vbox) # 將垂直佈局加到佈局器中(按鈕位於頁面右下角) if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() ex.show() sys.exit(app.exec_())
3)柵格化佈局
import sys from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QApplication, QPushButton, QWidget, QGridLayout class Example(QWidget): def __init__(self): super().__init__() self.initUI() self.Grid() def initUI(self): self.setGeometry(100, 100, 500, 500) self.setWindowTitle('Statusbar') def Grid(self): # 柵格化的按鈕 grid = QGridLayout() # 建立一個柵格化佈局 name = ["7", "8", "9", "/", "4", "5", "6", "x", "1", "2", "3", "-", "清除", "0", ".", "="] # 列表推導式 pos = [(x, y) for x in range(4) for y in range(4)] for names, p in zip(name, pos): # 同時迭代兩個序列 button = QPushButton(names) # 建立按鈕 grid.setSpacing(10) # 設定各個單元格之間的間距 grid.addWidget(button, *p) # 新增到柵格化佈局中 self.setLayout(grid) # 將柵格化佈局加到佈局器 if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() ex.show() sys.exit(app.exec_())
效果圖
柵格化佈局理論上也是透過座標來定位的,透過列表推導式可到得到幾個座標(0,0)(0,1)(0,2)(1,0)(1,1)(1,2)..........,然後再透過座標去逐個新增。
4)例項
import sys from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QLabel, QApplication,QWidget, QGridLayout, \ QLineEdit, QTextEdit class Example(QWidget): def __init__(self): super().__init__() self.initUI() self.input() def initUI(self): self.setGeometry(100, 100, 500, 500) self.setWindowTitle('Statusbar') def input(self): grid = QGridLayout() # 設定標籤 title = QLabel("title") Author = QLabel("Author") Review = QLabel("Review") # 設定輸入框 titleEdit = QLineEdit() # 行編輯 authorEdit = QLineEdit() reviewEdit = QTextEdit() # 文版編輯 grid.setSpacing(10) # 設定間距 grid.addWidget(title, 0, 0) grid.addWidget(titleEdit, 0, 1) grid.addWidget(Author, 1, 0) grid.addWidget(authorEdit, 1, 1) grid.addWidget(Review, 2, 0) grid.addWidget(reviewEdit, 2, 1) self.setLayout(grid) if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() ex.show() sys.exit(app.exec_())
上述中例項透過QGridLayout()來將QLabel(), QLineEdit(行編輯) ,QTextEdit(文版編輯) 進行的整合使用,下面看下結果。
四.例項
以一個簡單計算器功能為例,先來看下程式碼實現和效果展示
import sys from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QApplication, QPushButton, QWidget, QGridLayout, \ QLineEdit class Example(QWidget): def __init__(self): super().__init__() self.initUI() self.Grid() def initUI(self): self.setGeometry(100, 100, 500, 500) self.setWindowTitle('Statusbar') def Grid(self): # 柵格化的按鈕 grid = QGridLayout() hbox = QLineEdit() grid.addWidget(hbox, 0, 0, 1, 4) name = [ "7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", "清除", "0", ".", "="] # 列表推導式 pos = [(x, y) for x in range(1,5) for y in range(4)] for names, p in zip(name, pos): # 同時迭代兩個序列 if names == "": continue elif names == "hbox": grid.addWidget(hbox, *p) else: button = QPushButton(names) grid.addWidget(button, *p) button.clicked.connect(lambda checked, btn_text=names: on_button_clicked(btn_text)) grid.setSpacing(10) # 設定各個單元格之間的間距 self.setLayout(grid) def on_button_clicked(btn_text): try: if btn_text == "清除": hbox.clear() elif btn_text == "=": str_num = eval(hbox.text()) hbox.clear() hbox.insert(str(str_num)) else: hbox.insert(btn_text) except: hbox.insert("error") if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() ex.show() sys.exit(app.exec_())
使用addWidget將輸入框新增到柵格化佈局中,後面無個引數分別表示:(新增物件,x位置,y位置,佔據的單元格高度,佔據的單元格寬度)。
grid.addWidget(hbox, 0, 0, 1, 4)
QLineEdit()幾個常用的方法
hbox = QLineEdit() hbox.setText("預設文案") # 設定預設文案 hbox.setPlaceholderText("暗文") # 當輸入框內容為空時顯示該文案 hbox.insert("243") # 新增 print(hbox.text()) # 獲取框內容 hbox.clear() # 清空
五.打包
可參考:https://www.cnblogs.com/lihongtaoya/p/17349911.html
文章來源:https://www.cnblogs.com/lihongtaoya/ ,請勿轉載