Python桌面應用開發(fā)實戰(zhàn)之PyQt的安裝使用
引言:桌面應用開發(fā)三大框架介紹
Tkinter:優(yōu)勢是免安裝、相對簡單,缺點是功能少,無界面設計工具。
PyQT:使用率高,功能最為強大,代碼可維護性和易讀性高。
WxPython:介于Tkinter和PyQT之間,相當于壓縮版QT。
總結(jié):三種框架各有優(yōu)劣,有時間可以全部學習,并不復雜。如果只選一種,這里推薦使用最主流、最保值、上限最高的PyQT。
一、PyQT介紹
Qt:Qt是一個跨平臺的C++圖形用戶界面應用程序開發(fā)框架,目前已成為最強大,最受歡迎的跨平臺GUI庫之一。Qt不僅可以開發(fā)GUI程序,也可開發(fā)非GUI程序,比如控制臺工具和服務程序。
PyQt:PyQt是Qt的Python封裝,提供Qt類和函數(shù)的API。
PyQt6的官網(wǎng):https://www.riverbankcomputing.co.uk/news
可以參考的中文手冊:https://www.syrr.cn/news/415861.html?action=onClick
PyQt常用模塊:
QtWidgets模塊:包含應用程序類、窗口類、控件類和組件類
QtGui模塊:包含和gui相關(guān)的功能,例如用于事件處理、圖像處理、字體和顏色類等
QtCore模塊:包含核心的非gui功能,例如線程、定時器、日期時間類、文件類等
二、安裝
安裝: pip install PyQt6
檢查安裝版本(進入python命令行):
from PyQt6.QtCore import QT_VERSION_STR, PYQT_VERSION_STR QT_VERSION_STR, PYQT_VERSION_STR
三、使用教程
(1)基礎(chǔ)窗口
import sys from PyQt6.QtWidgets import QApplication, QWidget, QLabel from PyQt6.QtGui import QIcon, QFont from PyQt6.QtCore import Qt #從QWidget類派生的桌面應用程序窗口類 class MyWindow(QWidget): #QtWidgets模塊:包含應用程序類、窗口類、控件類和組件類 #構(gòu)造函數(shù) def __init__(self): super().__init__() # 調(diào)用基類的構(gòu)造函數(shù) self.setWindowTitle('Hello World') # 設置標題 #self.setWindowIcon(QIcon('res/qt.png')) # 可以設置圖標 lab = QLabel('Hello World', self) # 實例化標簽 lab.resize(320,160) # 設置標簽大小 lab.setFont(QFont('Arial', 32, QFont.Weight.Bold)) # 設置字體字號 lab.setAlignment(Qt.AlignmentFlag.AlignCenter) # 文本在標簽內(nèi)居中 self.show() # 顯示窗口 if __name__ == '__main__': app = QApplication(sys.argv) # 創(chuàng)建應用程序,接收來自命令行的參數(shù)列表 win = MyWindow() # 創(chuàng)建窗口,這里初始化的時候不需要QWidget入?yún)? sys.exit(app.exec()) # 應用程序主循環(huán)結(jié)束后,調(diào)用sys.exit()方法清理現(xiàn)場
執(zhí)行后結(jié)果如下:
(2)分區(qū)布局窗口(類似于html中div的使用)
import sys from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QHBoxLayout, QVBoxLayout from PyQt6.QtGui import QIcon from PyQt6.QtCore import Qt class MyWindow(QWidget): def __init__(self): super().__init__() self.setWindowTitle('分區(qū)布局') self.setGeometry(400, 300, 320, 160) # 設置窗位置和大小 lab_acc = QLabel('賬號:') # 實例化標簽 account = QLineEdit() #單行文本編輯框 account.setAlignment(Qt.AlignmentFlag.AlignCenter) # 文本在標簽內(nèi)居中 lab_pw = QLabel('密碼:') passwd = QLineEdit() passwd.setAlignment(Qt.AlignmentFlag.AlignCenter) passwd.setEchoMode(QLineEdit.EchoMode.Password) # 不顯示密碼 btn_ok = QPushButton('確定') #按鈕 btn_cancel = QPushButton('取消') # 使用水平布局管理器布局lab_acc控件和account控件,左右留白10像素 hbox_acc = QHBoxLayout() #水平布局管理器 hbox_acc.addSpacing(10) #水平布局間隔 hbox_acc.addWidget(lab_acc) #將實例化標簽賬號放入 hbox_acc.addWidget(account) #將#單行文本編輯框放入 hbox_acc.addSpacing(10) # 使用水平布局管理器布局lab_pw控件和passwd控件,左右留白10像素 hbox_pw = QHBoxLayout() #垂直布局管理器 hbox_pw.addSpacing(10) hbox_pw.addWidget(lab_pw) hbox_pw.addWidget(passwd) hbox_pw.addSpacing(10) # 使用水平布局管理器布局btn_ok控件和btn_cancel控件 hbox_btn = QHBoxLayout() # 水平布局管理器 hbox_btn.addStretch(5) # 設置左側(cè)拉伸因子 hbox_btn.addWidget(btn_ok) # 添加btn_ok控件 hbox_btn.addWidget(btn_cancel) # 添加btn_cancel控件 hbox_btn.addStretch(1) # 設置右側(cè)拉伸因子 # 使用垂直布局管理器布局上面3個水平布局管理器 vbox = QVBoxLayout() vbox.addSpacing(10) vbox.addLayout(hbox_acc) vbox.addSpacing(5) vbox.addLayout(hbox_pw) vbox.addStretch(1) vbox.addLayout(hbox_btn) vbox.addSpacing(10) # 將垂直布局管理器應用到窗口 self.setLayout(vbox) self.show() # 顯示窗口 if __name__ == '__main__': app = QApplication(sys.argv) win = MyWindow() sys.exit(app.exec())
執(zhí)行后結(jié)果如下:
(3)柵格布局窗口(類似于html中的table)
import sys from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QGridLayout from PyQt6.QtGui import QIcon class MyWindow(QWidget): def __init__(self): super().__init__() self.setWindowTitle('柵格布局') self.initUI() # 初始化界面 self.show() # 顯示窗口 def initUI(self): #創(chuàng)建一個5*5的數(shù)組,后面會逐一放入柵格 keys = [ ['(', ')', 'Back', 'Clear'], ['7', '8', '9', '/'], ['4', '5', '6', '*'], ['1', '2', '3', '-'], ['0', '.', '=', '+'] ] grid = QGridLayout() # 創(chuàng)建網(wǎng)格布局管理器 self.setLayout(grid) # 將網(wǎng)格布局管理器應用到窗口 for i in range(5): for j in range(4): button = QPushButton(keys[i][j]) grid.addWidget(button, i, j) #將元素放入柵格,i是橫坐標,j是縱坐標 if __name__ == '__main__': app = QApplication(sys.argv) win = MyWindow() sys.exit(app.exec())
執(zhí)行后結(jié)果如下:
(4)表單布局窗口(類似于html中的form)
import sys from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QVBoxLayout, QFormLayout from PyQt6.QtGui import QIcon from PyQt6.QtCore import Qt class MyWindow(QWidget): def __init__(self): super().__init__() self.setWindowTitle('表單布局') self.setGeometry(400, 300, 320, 200) # 設置窗位置和大小 form = QFormLayout() # 創(chuàng)建表單布局管理器 form.setLabelAlignment(Qt.AlignmentFlag.AlignRight) #設置標簽右對齊(默認左對齊) name = QLineEdit() #單行文本編輯框 mobile = QLineEdit() passwd = QLineEdit() addr = QLineEdit() form.addRow('姓名', name) #將文本放入form中 form.addRow('移動電話', mobile) form.addRow('密碼', passwd) form.addRow('通訊地址', addr) name.setPlaceholderText("請輸入姓名") #設置placeholder灰體默認值 mobile.setPlaceholderText("請輸入移動電話") passwd.setPlaceholderText("請輸入密碼") addr.setPlaceholderText("請輸入通訊地址") name.setEchoMode(QLineEdit.EchoMode.Normal) #EchoMode為Normal:顯示輸入的字符。這是默認值 mobile.setEchoMode(QLineEdit.EchoMode.NoEcho) #EchoMode為NoEcho:不顯示任何東西。這可能適用于連密碼長度都應該保密的密碼。 passwd.setEchoMode(QLineEdit.EchoMode.Password) #EchoMode為Password:顯示平臺相關(guān)的密碼掩碼字符,而不是實際輸入的字符。 addr.setEchoMode(QLineEdit.EchoMode.PasswordEchoOnEdit) #EchoMode為PasswordEchoOnEdit:在編輯時顯示輸入的字符,否則顯示與密碼相同的字符。 btn_ok = QPushButton('確定') vbox = QVBoxLayout() #垂直布局管理器布局 vbox.addSpacing(10) vbox.addLayout(form) vbox.addStretch(1) vbox.addWidget(btn_ok, alignment=Qt.AlignmentFlag.AlignCenter) vbox.addSpacing(10) # 將垂直布局管理器應用到窗口 self.setLayout(vbox) self.show() # 顯示窗口 if __name__ == '__main__': app = QApplication(sys.argv) win = MyWindow() sys.exit(app.exec())
執(zhí)行后結(jié)果如下:
(5)事件函數(shù)與事件過濾器
常用的事件函數(shù)如下:
keyPressEvent(): 鍵盤按下事件 keyReleaseEvent(): 鍵盤釋放事件
mouseDoubleClickEvent(): 鼠標雙擊事件
mouseMoveEvent(): 鼠標移動事件
mousePressEvent(): 鼠標按下事件
mouseReleaseEvent(): 鼠標釋放事件
timerEvent(): 定時器事件
dragEnterEvent(): 拖拽進入當前窗口事件
dragLeaveEvent(): 拖拽離開當前窗口事件
dragMoveEvent(): 拖拽移動事件
enterEvent(): 進入窗口區(qū)域事件
leaveEvent(): 離開窗口區(qū)域事件
closeEvent(): 關(guān)閉窗口事件
示例1–事件函數(shù):
import sys from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QHBoxLayout from PyQt6.QtCore import Qt class MyWindow(QWidget): def __init__(self): super().__init__() self.setWindowTitle('事件和事件函數(shù)') self.setGeometry(400, 300, 320, 80) self.initUI() # 初始化界面 self.show() def initUI(self): lab = QLabel('按Esc鍵關(guān)閉窗口') box = QHBoxLayout() box.addStretch(1) box.addWidget(lab) box.addStretch(1) self.setLayout(box) #重寫"鍵盤按下事件"的事件函數(shù),指定ESC鍵作為觸發(fā)事件的鍵(如果不指定就是所有鍵都會觸發(fā)事件) def keyPressEvent(self, evt): if evt.key() == Qt.Key.Key_Escape.value: #Qt.Key對應的鍵盤下面有對照表 self.close() if __name__ == '__main__': app = QApplication(sys.argv) win = MyWindow() sys.exit(app.exec())
執(zhí)行后結(jié)果如下:
Qt.Key對應的鍵盤對照如下:
Qt::Key_Escape 0x01000000 Esc鍵
Qt::Key_Tab 0x01000001 Tab鍵 Qt::Key_Backtab 0x01000002 Tab補全鍵
Qt::Key_Backspace 0x01000003 退格鍵 Qt::Key_Return 0x01000004 Return鍵
Qt::Key_Enter 0x01000005 回車鍵 Qt::Key_Insert 0x01000006 Insert鍵
Qt::Key_Delete 0x01000007 Delete鍵 Qt::Key_Pause 0x01000008 暫停鍵
Qt::Key_Print 0x01000009 截圖鍵 Qt::Key_SysReq 0x0100000a PrtSc
Qt::Key_Clear 0x0100000b 清除鍵 Qt::Key_Home 0x01000010 Home鍵
Qt::Key_End 0x01000011 End鍵 Qt::Key_Left 0x01000012 ←
Qt::Key_Up 0x01000013 ↑ Qt::Key_Right 0x01000014 →
Qt::Key_Down 0x01000015 ↓ Qt::Key_PageUp 0x01000016 上頁
Qt::Key_PageDown 0x01000017 下頁 Qt::Key_Shift 0x01000020 Shift鍵
Qt::Key_Control 0x01000021 Ctrl鍵 Qt::Key_Alt 0x01000023 Alt鍵
Qt::Key_AltGr 0x01001103 右側(cè)Alt Qt::Key_CapsLock 0x01000024 大寫鍵
Qt::Key_NumLock 0x01000025 NumLock Qt::Key_ScrollLock 0x01000026 滾動鎖定
Qt::Key_F1 0x01000030 F1~F12 Qt::Key_F2 0x01000031
Qt::Key_F3 0x01000032 Qt::Key_F4 0x01000033 Qt::Key_F5 0x01000034
Qt::Key_F6 0x01000035 Qt::Key_F7 0x01000036 Qt::Key_F8 0x01000037
Qt::Key_F9 0x01000038 Qt::Key_F10 0x01000039
Qt::Key_F11 0x0100003a Qt::Key_F12 0x0100003b
Qt::Key_Menu 0x01000055 菜單鍵 Qt::Key_Help 0x01000058 Help鍵
Qt::Key_Space 0x20 空格鍵 Qt::Key_Exclam 0x21 ! Qt::Key_QuoteDbl 0x22 引用
Qt::Key_NumberSign 0x23 # Qt::Key_Dollar 0x24 $ Qt::Key_Percent 0x25 %
Qt::Key_Ampersand 0x26 & Qt::Key_Apostrophe 0x27 分詞符" ’ "
Qt::Key_ParenLeft 0x28 ( Qt::Key_ParenRight 0x29 )
Qt::Key_Asterisk 0x2a * Qt::Key_Plus 0x2b + Qt::Key_Comma 0x2c ,
Qt::Key_Minus 0x2d - Qt::Key_Period 0x2e 。 Qt::Key_Slash 0x2f /
Qt::Key_0 0x30 數(shù)字0~9 Qt::Key_1 0x31 Qt::Key_2 0x32 Qt::Key_3 0x33
Qt::Key_4 0x34 Qt::Key_5 0x35 Qt::Key_6 0x36 Qt::Key_7 0x37
Qt::Key_8 0x38 Qt::Key_9 0x39 Qt::Key_Colon 0x3a :
Qt::Key_Semicolon 0x3b ; Qt::Key_Less 0x3c < Qt::Key_Equal 0x3d 等于
Qt::Key_Greater 0x3e > Qt::Key_Question 0x3f ? Qt::Key_At 0x40 @
Qt::Key_A 0x41 字母鍵 Qt::Key_B 0x42 Qt::Key_C 0x43 Qt::Key_D 0x44
Qt::Key_E 0x45 Qt::Key_F 0x46 Qt::Key_G 0x47 Qt::Key_H 0x48
Qt::Key_I 0x49 Qt::Key_J 0x4a Qt::Key_K 0x4b Qt::Key_L 0x4c
Qt::Key_M 0x4d Qt::Key_N 0x4e Qt::Key_O 0x4f Qt::Key_P 0x50
Qt::Key_Q 0x51 Qt::Key_R 0x52 Qt::Key_S 0x53 Qt::Key_T 0x54
Qt::Key_U 0x55 Qt::Key_V 0x56 Qt::Key_W 0x57 Qt::Key_X 0x58
Qt::Key_Y 0x59 Qt::Key_Z 0x5a Qt::Key_BracketLeft 0x5b [
Qt::Key_Backslash 0x5c \ Qt::Key_BracketRight 0x5d ]
Qt::Key_AsciiCircum 0x5e ^ Qt::Key_Underscore 0x5f _
Qt::Key_QuoteLeft 0x60 “ Qt::Key_BraceLeft 0x7b { Qt::Key_Bar 0x7c |
Qt::Key_BraceRight 0x7d } Qt::Key_AsciiTilde 0x7e ~
Qt::Key_nobreakspace 0x0a0 不換行空格 Qt::Key_exclamdown 0x0a1 !
示例2–事件過濾器:
(在剛才的基礎(chǔ)上增加導入QEvent,添加eventFilter方法,并在最后執(zhí)行installEventFilter方法)
import sys from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QHBoxLayout from PyQt6.QtCore import Qt, QEvent class MyWindow(QWidget): def __init__(self): super().__init__() self.setWindowTitle('事件和事件函數(shù)') self.setGeometry(400, 300, 320, 80) self.initUI() # 初始化界面 self.show() def initUI(self): lab = QLabel('按Esc鍵關(guān)閉窗口') box = QHBoxLayout() box.addStretch(1) box.addWidget(lab) box.addStretch(1) self.setLayout(box) #重寫"鍵盤按下事件"的事件函數(shù),指定ESC鍵作為觸發(fā)事件的鍵(如果不指定就是所有鍵都會觸發(fā)事件) def keyPressEvent(self, evt): if evt.key() == Qt.Key.Key_Escape.value: self.close() #事件過濾方法 def eventFilter(self, objwatched, evt): if evt.type() == QEvent.Type.KeyPress.value: print('忽略按鍵事件') return True return super().eventFilter(objwatched, evt) if __name__ == '__main__': app = QApplication(sys.argv) win = MyWindow() app.installEventFilter(win) #安裝本對象的事件過濾器 sys.exit(app.exec())
此時按Esc鍵無法關(guān)閉窗口
(6)信號和槽
介紹:信號(signal)和槽(slot)是Qt的核心機制,也是在PyQt編程中對象之間進行通信的機制。在創(chuàng)建事件循環(huán)之后,通過建立信號和槽的連接就可以實現(xiàn)對象之間的通信。當信號發(fā)射(emit)時,連接的槽函數(shù)將會自動執(zhí)行。
示例1–使用內(nèi)置的信號和槽:
import sys from PyQt6.QtWidgets import QPushButton, QMessageBox, QApplication, QWidget class Window(QWidget): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.setWindowTitle('按鈕事件') self.resize(300, 200) self.btn = QPushButton('按鈕', self) self.init_ui() def init_ui(self): self.btn.resize(100, 30) self.btn.move(100, 50) #按鈕的位置 self.btn.clicked.connect(self.btn_hand) #使用connect綁定事件,點擊按鈕時觸發(fā) self.close() def btn_hand(self): widget = QWidget() QMessageBox.information(widget, 'Pop messgae', 'OK') #觸發(fā)的事件時彈出會話框 if __name__ == "__main__": app = QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec())
運行結(jié)果如下:
示例2–自定義信號和槽函數(shù)示例:
import sys from PyQt6.QtCore import pyqtSignal, Qt from PyQt6.QtWidgets import * class WinForm(QWidget): # 自定義信號,不帶參數(shù) button_clicked_signal = pyqtSignal() def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle('自定義信號和槽函數(shù)示例') self.resize(300, 150) # 接收信號,連接到自定義槽函數(shù) self.button_clicked_signal.connect(self.pop_message) def pop_message(self): QMessageBox.information(self, 'Pop messgae', 'OK') def mousePressEvent(self, event): # 重寫鼠標按下事件 super().mousePressEvent(event) if event.button() == Qt.MouseButton.LeftButton: # 當鼠標左鍵單擊時 self.button_clicked_signal.emit() # 發(fā)射信號 if __name__ == '__main__': app = QApplication(sys.argv) win = WinForm() win.show() sys.exit(app.exec())
運行結(jié)果如下:
示例三–結(jié)合信號和槽進行多線程操作:
import sys from PyQt6.QtWidgets import QApplication,QMainWindow,QWidget,QProgressBar,QVBoxLayout,QPushButton from PyQt6.QtCore import QThread,QObject,pyqtSignal,Qt #線程函數(shù) class CountSever(QObject): _isrun = False #線程是否運行全局變量 countupdate = pyqtSignal() #自定義信號 #構(gòu)造函數(shù) def __init__(self, interval) -> None: #-> None 表示返回的數(shù)值類型不受限制 super().__init__() self.interval = interval #執(zhí)行間隔,初始化的時候在構(gòu)造函數(shù)中指定,如self.cs1 = CountSever(100)代表每100ms執(zhí)行一次 #判斷單個線程是否運行 def isrun(self,value:bool): self._isrun = value #線程運行函數(shù) def run(self): while True: pass while self._isrun: self.countupdate.emit() #當線程運行時發(fā)射自定義信號 QThread.msleep(self.interval) #設置線程執(zhí)行間隔 #進度條主界面,QMainWindow--頂層窗口類,重量級控件。 class MainWindow(QMainWindow): countstart = pyqtSignal(bool) #自定義信號對象 def __init__(self) -> None: #-> None 表示返回的數(shù)值類型不受限制 super().__init__() self.init_ui() self.setcenter() #調(diào)用下面的居中方法 def init_ui(self): self.setWindowTitle("線程刷新進度條") self.resize(400, 300) self.main_widget = QWidget() self.setCentralWidget(self.main_widget) #居中展示 self.main_layout = QVBoxLayout() ##垂直布局管理器布局 self.main_layout.setAlignment(Qt.AlignmentFlag.AlignHCenter) self.main_widget.setLayout(self.main_layout) #設置四個進度條 self.progress_1 = QProgressBar(self) #ProgressBar提供了一個水平或垂直的進度條,可以使用setMinimum()和setMaximum指定最小和最大步數(shù) self.progress_1.setRange(0,100) self.main_layout.addWidget(self.progress_1) #在頁面布局中添加進度條控件 self.progress_2 = QProgressBar(self) self.progress_2.setRange(0,100) self.main_layout.addWidget(self.progress_2) self.main_layout.addStretch(1) self.progress_3 = QProgressBar(self) self.progress_3.setRange(0, 100) self.main_layout.addWidget(self.progress_3) self.progress_4 = QProgressBar(self) self.progress_4.setRange(0, 100) self.main_layout.addWidget(self.progress_4) self.btn_start = QPushButton("Start") self.btn_start.setFixedSize(120,30) #點擊start按鈕觸發(fā)下面定義的start方法,start方法會根據(jù)當前按鈕發(fā)送True/Flase的信號給countstart自定義對象,然后這個True/Flase決定了isrun的結(jié)果,決定線程是否運行 self.btn_start.clicked.connect(self.start) self.main_layout.addWidget(self.btn_start) #將開始按鈕放入布局中 self.main_layout.setAlignment(self.btn_start,Qt.AlignmentFlag.AlignCenter) # thread self.cs1 = CountSever(100) #每100ms執(zhí)行一次 #自定義信號綁定下面的事件countupdate,下面的 self.progress_1.setValue(self.progress_1.value() + 1)表示執(zhí)行一次進度條progress_1的值加一,range值是0-100,加到100便會停止線程 self.cs1.countupdate.connect(self.countupdate) self.countstart.connect(self.cs1.isrun) #自定義信號綁定下面的事件:判斷線程是否在運行 self.th1 = QThread() self.cs1.moveToThread(self.th1) #moveToThread函數(shù):給多個任務各分配一個線程去執(zhí)行 self.th1.started.connect(self.cs1.run) #QThread提供了QThread::started()(當線程開始時發(fā)射)和QThread::finished()(在線程運行結(jié)束后發(fā)射)兩個信號 self.th1.start() #線程開始執(zhí)行 self.cs2 = CountSever(150) self.cs2.countupdate.connect(self.countupdate) self.countstart.connect(self.cs2.isrun) self.th2 = QThread() self.cs2.moveToThread(self.th2) self.th2.started.connect(self.cs2.run) self.th2.start() self.cs3 = CountSever(1000) self.cs3.countupdate.connect(self.countupdate) self.countstart.connect(self.cs3.isrun) self.th3 = QThread() self.cs3.moveToThread(self.th3) self.th3.started.connect(self.cs3.run) self.th3.start() self.cs4 = CountSever(1500) self.cs4.countupdate.connect(self.countupdate) self.countstart.connect(self.cs4.isrun) self.th4 = QThread() self.cs4.moveToThread(self.th4) self.th4.started.connect(self.cs4.run) self.th4.start() def setcenter(self): #界面居中顯示 win_rect = self.frameGeometry() screen_center = self.screen().availableGeometry().center() win_rect.moveCenter(screen_center) self.move(win_rect.topLeft()) #start方法會根據(jù)當前按鈕發(fā)送True/Flase的信號給countstart自定義對象,然后這個True/Flase決定了isrun的結(jié)果,決定線程是否運行 def start(self): if self.btn_start.text() == "Start": self.countstart.emit(True) self.btn_start.setText("Pause") elif self.btn_start.text() == "Pause": self.countstart.emit(False) self.btn_start.setText("Start") def countupdate(self): if self.sender() == self.cs1: self.progress_1.setValue(self.progress_1.value() + 1) #表示執(zhí)行一次進度條progress_1的值加一,range值是0-100,加到100便會停止線程 elif self.sender() == self.cs2: self.progress_2.setValue(self.progress_2.value() + 1) elif self.sender() == self.cs3: self.progress_3.setValue(self.progress_3.value() + 1) elif self.sender() == self.cs4: self.progress_4.setValue(self.progress_4.value() + 1) if __name__ == "__main__": """ 主程序運行 """ app = QApplication(sys.argv) main_window = MainWindow() main_window.show() sys.exit(app.exec())
運行結(jié)果如下:
四、實戰(zhàn)示例
(1)狀態(tài)欄(追蹤鼠標移動軌跡)
import sys from PyQt6.QtWidgets import QApplication, QMainWindow, QWidget, QLabel, QHBoxLayout from PyQt6.QtGui import QIcon, QPixmap from PyQt6.QtCore import Qt class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle('狀態(tài)欄') self.initUI() # 初始化界面 self.center() # 窗口在屏幕上居中 self.show() # 顯示窗口 def center(self): win_rect = self.frameGeometry() # 窗口矩形(QRect類) scr_center = self.screen().availableGeometry().center() # 屏幕中心 win_rect.moveCenter(scr_center) # 窗口矩形中心移動到屏幕中心 self.move(win_rect.topLeft()) # 移動窗口和窗口矩形重合 def initUI(self): self.resize(400, 300) lab = QLabel() box = QHBoxLayout() box.addWidget(lab) self.main_widget = QWidget() self.main_widget.setLayout(box) self.setCentralWidget(self.main_widget) # 對于需要處理鼠標移動事件的部件,開啟感知鼠標移動軌跡 lab.setMouseTracking(True) self.main_widget.setMouseTracking(True) self.setMouseTracking(True) self.sbar = self.statusBar() # 返回窗口狀態(tài)欄 self.mouth_info = QLabel() # 顯示鼠標坐標的標簽 self.sbar.addPermanentWidget(self.mouth_info) # 將顯示鼠標坐標的標簽添加到狀態(tài)欄 self.sbar.addPermanentWidget(QLabel('版權(quán)所有 ')) # 將版權(quán)聲明添加到狀態(tài)欄 self.sbar.showMessage('準備就緒', 3000) # 顯示消息,3秒鐘后消失 def enterEvent(self, evt): """響應鼠標進入窗口事件""" #QStatusBar.showMessage(str, msecs=0):顯示str消息持續(xù)msecs毫秒。如果msecs為0(默認),則消息將一直顯示,直到調(diào)用clearMessage()或再次showMessage以更改消息。 self.sbar.showMessage('鼠標進入', 3000) def leaveEvent(self, evt): """響應鼠標離開窗口事件""" self.sbar.showMessage('鼠標離開', 3000) self.mouth_info.setText('') def mouseMoveEvent(self, evt): """響應鼠標移動事件""" pos = evt.position() self.mouth_info.setText('x=%d, y=%d '%(pos.x(), pos.y())) if __name__ == '__main__': app = QApplication(sys.argv) win = MainWindow() sys.exit(app.exec())
運行結(jié)果如下:
(2)菜單欄
import sys from PyQt6.QtWidgets import QApplication, QMainWindow from PyQt6.QtGui import QIcon, QAction class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle('菜單欄') self.resize(250, 150) self.initUI() # 初始化界面 self.center() # 窗口在屏幕上居中 self.show() # 顯示窗口 def center(self): win_rect = self.frameGeometry() # 窗口矩形(QRect類) scr_center = self.screen().availableGeometry().center() # 屏幕中心 win_rect.moveCenter(scr_center) # 窗口矩形中心移動到屏幕中心 self.move(win_rect.topLeft()) # 移動窗口和窗口矩形重合 def initUI(self): self.sbar = self.statusBar() # 返回窗口狀態(tài)欄 #openAction = QAction(QIcon('res/open_mso.png'), '&打開', self) 可以在第一個參數(shù)設置圖片 openAction = QAction('&打開', self) openAction.setShortcut('Ctrl+O') #設置快捷鍵 openAction.setStatusTip('打開文件') #設置狀態(tài)提示文字 openAction.triggered.connect(lambda : print('此處彈出打開文件的對話框')) saveAction = QAction('&保存', self) saveAction.setShortcut('Ctrl+S') saveAction.setStatusTip('保存文件') saveAction.triggered.connect(lambda : print('此處彈出保存文件的對話框')) quitAction = QAction('&退出', self) quitAction.setShortcut('Ctrl+Q') quitAction.setStatusTip('退出程序') quitAction.triggered.connect(self.close) singleAction = QAction('&個人權(quán)限', self) singleAction.setStatusTip('個人權(quán)限') singleAction.triggered.connect(lambda : print('此處響應個人權(quán)限操作')) groupAction = QAction('&組權(quán)限', self) groupAction.setStatusTip('組權(quán)限') groupAction.triggered.connect(lambda : print('此處響應組權(quán)限操作')) mb = self.menuBar() fm = mb.addMenu('&文件') fm.addAction(openAction) fm.addAction(saveAction) fm.addSeparator() subMenu = fm.addMenu('權(quán)限') subMenu.addAction(singleAction) subMenu.addAction(groupAction) fm.addSeparator() fm.addAction(quitAction) if __name__ == '__main__': app = QApplication(sys.argv) win = MainWindow() sys.exit(app.exec())
運行結(jié)果如下:
(3)工具欄
import sys from PyQt6.QtWidgets import QApplication, QMainWindow, QToolBar from PyQt6.QtGui import QIcon, QAction from PyQt6.QtCore import Qt class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle('工具欄') self.resize(400, 300) self.initUI() # 初始化界面 self.center() # 窗口在屏幕上居中 self.show() # 顯示窗口 def center(self): win_rect = self.frameGeometry() # 窗口矩形(QRect類) scr_center = self.screen().availableGeometry().center() # 屏幕中心 win_rect.moveCenter(scr_center) # 窗口矩形中心移動到屏幕中心 self.move(win_rect.topLeft()) # 移動窗口和窗口矩形重合 def initUI(self): self.sbar = self.statusBar() # 返回窗口狀態(tài)欄 import sys from PyQt6.QtWidgets import QApplication, QMainWindow, QToolBar from PyQt6.QtGui import QIcon, QAction from PyQt6.QtCore import Qt class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle('工具欄') self.resize(400, 300) self.initUI() # 初始化界面 self.center() # 窗口在屏幕上居中 self.show() # 顯示窗口 def center(self): win_rect = self.frameGeometry() # 窗口矩形(QRect類) scr_center = self.screen().availableGeometry().center() # 屏幕中心 win_rect.moveCenter(scr_center) # 窗口矩形中心移動到屏幕中心 self.move(win_rect.topLeft()) # 移動窗口和窗口矩形重合 def initUI(self): self.sbar = self.statusBar() # 返回窗口狀態(tài)欄 #openAction = QAction(QIcon('res/open_mso.png'), '&打開', self) 可添加圖標圖片 openAction = QAction('&打開', self) openAction.setShortcut('Ctrl+O') openAction.setStatusTip('打開文件') openAction.triggered.connect(lambda : print('此處彈出打開文件的對話框')) saveAction = QAction('&保存', self) saveAction.setShortcut('Ctrl+S') saveAction.setStatusTip('保存文件') saveAction.triggered.connect(lambda : print('此處彈出保存文件的對話框')) quitAction = QAction('&退出', self) quitAction.setShortcut('Ctrl+Q') quitAction.setStatusTip('退出程序') quitAction.triggered.connect(self.close) singleAction = QAction('&個人權(quán)限', self) singleAction.setStatusTip('個人權(quán)限') singleAction.triggered.connect(lambda : print('此處響應個人權(quán)限操作')) groupAction = QAction('&組權(quán)限', self) groupAction.setStatusTip('組權(quán)限') groupAction.triggered.connect(lambda : print('此處響應組權(quán)限操作')) mb = self.menuBar() fm = mb.addMenu('&文件') fm.addAction(openAction) fm.addAction(saveAction) fm.addSeparator() #添加分割線 subMenu = fm.addMenu('權(quán)限') subMenu.addAction(singleAction) subMenu.addAction(groupAction) fm.addSeparator() fm.addAction(quitAction) tb = self.addToolBar('文件') tb.addAction(openAction) tb.addAction(saveAction) tb = self.addToolBar('退出') tb.addAction(quitAction) tb = QToolBar(self) tb.setObjectName('權(quán)限') self.addToolBar(Qt.ToolBarArea.RightToolBarArea, tb) tb.addAction(singleAction) tb.addAction(groupAction) if __name__ == '__main__': app = QApplication(sys.argv) win = MainWindow() sys.exit(app.exec()) openAction = QAction('&打開', self) openAction.setShortcut('Ctrl+O') openAction.setStatusTip('打開文件') openAction.triggered.connect(lambda : print('此處彈出打開文件的對話框')) saveAction = QAction('&保存', self) saveAction.setShortcut('Ctrl+S') saveAction.setStatusTip('保存文件') saveAction.triggered.connect(lambda : print('此處彈出保存文件的對話框')) quitAction = QAction('&退出', self) quitAction.setShortcut('Ctrl+Q') quitAction.setStatusTip('退出程序') quitAction.triggered.connect(self.close) singleAction = QAction('&個人權(quán)限', self) singleAction.setStatusTip('個人權(quán)限') singleAction.triggered.connect(lambda : print('此處響應個人權(quán)限操作')) groupAction = QAction('&組權(quán)限', self) groupAction.setStatusTip('組權(quán)限') groupAction.triggered.connect(lambda : print('此處響應組權(quán)限操作')) mb = self.menuBar() fm = mb.addMenu('&文件') fm.addAction(openAction) fm.addAction(saveAction) fm.addSeparator() #添加分割線 subMenu = fm.addMenu('權(quán)限') subMenu.addAction(singleAction) subMenu.addAction(groupAction) fm.addSeparator() fm.addAction(quitAction) tb = self.addToolBar('文件') tb.addAction(openAction) tb.addAction(saveAction) tb = self.addToolBar('退出') tb.addAction(quitAction) tb = QToolBar(self) tb.setObjectName('權(quán)限') self.addToolBar(Qt.ToolBarArea.RightToolBarArea, tb) tb.addAction(singleAction) tb.addAction(groupAction) if __name__ == '__main__': app = QApplication(sys.argv) win = MainWindow() sys.exit(app.exec())
運行結(jié)果如下:
(4)對話框
import sys, os from PyQt6.QtWidgets import QApplication, QMainWindow, QWidget, QPushButton, QGridLayout, QMessageBox, QInputDialog, QColorDialog, QFileDialog from PyQt6.QtGui import QIcon from PyQt6.QtCore import Qt class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle('對話框') self.initUI() self.show() def initUI(self): grid = QGridLayout() btns = [ ['通知消息', '警告消息', '錯誤消息', '確認消息', '關(guān)于'], ['顏色選擇', '保存文件', '打開文件', '選擇路徑', '輸入'] ] for i in (0, 1): for j in range(5): btn = QPushButton(btns[i][j]) btn.clicked.connect(self.on_button) grid.addWidget(btn, i, j) self.main_widget = QWidget() self.main_widget.setLayout(grid) self.setCentralWidget(self.main_widget) self.sbar = self.statusBar() self.sbar.showMessage('Ready', 5000) def on_button(self): """響應按鍵""" key = self.sender().text() #在槽函數(shù)種調(diào)用該方法可以返回信號的發(fā)出者 self.sbar.showMessage(key, 1000) #QMessageBox.information/warning/critical/question/about這幾個方法的圖標不一樣 #方法API--int QMessageBox::information(QWidget *parent, const QString &title, const QString &text, button0|button1|button2) #parent是父組件指針,title標題,text是文本文字,button0、1和 2是三個按鈕,每個按鈕間以|隔開。 if key == '通知消息': reply = QMessageBox.information(self, '提示', '對手認負,比賽結(jié)束。', QMessageBox.StandardButton.Ok ) self.sbar.showMessage(reply.name, 2000) elif key == '警告消息': reply = QMessageBox.warning(self, '警告', '不能連續(xù)提和!', QMessageBox.StandardButton.Ok ) self.sbar.showMessage(reply.name, 2000) elif key == '錯誤消息': reply = QMessageBox.critical(self, '錯誤', '著法錯誤!', QMessageBox.StandardButton.Retry|QMessageBox.StandardButton.Ignore|QMessageBox.StandardButton.Abort|QMessageBox.StandardButton.Cancel ) self.sbar.showMessage(reply.name, 2000) elif key == '確認消息': reply = QMessageBox.question(self, '請選擇', '對手提和,接受嗎?', QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No | QMessageBox.StandardButton.Cancel ) self.sbar.showMessage(reply.name, 2000) #把按鈕的選擇結(jié)果展示到左下角消息展示欄 elif key == '關(guān)于': QMessageBox.about(self, '關(guān)于', '云頂之弈 S9垃圾版本') elif key == '顏色選擇': color = QColorDialog.getColor() if color.isValid(): self.sbar.showMessage(color.name(), 2000) elif key == '保存文件': dase_dir = os.getcwd() file_type = 'Python Files (*.py);;Text Files (*.txt);;All Files (*)' #選擇需要保存的文件格式:python或者txt fname, fext = QFileDialog.getSaveFileName(self, '保存文件', directory=dase_dir, filter=file_type) if fname: self.sbar.showMessage(fname, 2000) elif key == '打開文件': dase_dir = os.getcwd() file_type = 'Python Files (*.py);;Text Files (*.txt);;All Files (*)' #選擇需要保存的文件格式:python或者txt fname = QFileDialog.getOpenFileName(self, '選擇文件', directory=dase_dir, filter=file_type) if fname[0]: self.sbar.showMessage(fname[0], 2000) elif key == '選擇路徑': dase_dir = os.getcwd() folder = QFileDialog.getExistingDirectory(self, '選擇文件夾', directory=dase_dir) self.sbar.showMessage(folder, 2000) elif key == '輸入': text, ok = QInputDialog.getText(self, '輸入對話框', '請輸入您的房間號碼:') if ok: self.sbar.showMessage(text, 2000) if __name__ == '__main__': app = QApplication(sys.argv) win = MainWindow() sys.exit(app.exec())
運行結(jié)果如下:
(5)相冊
import sys from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QHBoxLayout, QVBoxLayout from PyQt6.QtGui import QIcon, QPixmap class MyWindow(QWidget): def __init__(self): super().__init__() self.setWindowTitle('相冊') self.initUI() self.show() self.center() def center(self): """窗口在屏幕上居中""" win_rect = self.frameGeometry() scr_center = self.screen().availableGeometry().center() win_rect.moveCenter(scr_center) self.move(win_rect.topLeft()) def initUI(self): self.curr = 0 #注意這里要選三張圖片,放入當前pyhon腳本所在的文件夾的res目錄下,我這里之前放之前的截圖了 self.photos = ('D:/tools/python/srcipts2023/res/1.png', 'D:/tools/python/srcipts2023/res/2.png', 'D:/tools/python/srcipts2023/res/3.png') self.lab = QLabel() self.lab.setPixmap(QPixmap(self.photos[self.curr])) #用label標簽展示圖片,默認從列表第一個圖片,后面有根據(jù)按鈕切換圖片的方法 btn_prev = QPushButton('<') btn_next = QPushButton('>') btn_prev.clicked.connect(self.on_btn) btn_next.clicked.connect(self.on_btn) #設置邊框 hbox = QHBoxLayout() hbox.addStretch(1) hbox.addWidget(btn_prev) hbox.addSpacing(50) hbox.addWidget(btn_next) hbox.addStretch(1) vbox = QVBoxLayout() vbox.addWidget(self.lab) vbox.addLayout(hbox) self.setLayout(vbox) def on_btn(self): """響應按鍵""" key = self.sender().text() if key == '<': #點擊'<'按鈕時,取上一條圖片,一般來說按理來說(self.curr-1)就行,這里求余總數(shù)量的作用是為了能保持循環(huán),比如第一張前面沒有照片,就會跳到最后一張 #比如第一張時self.curr=0,(self.curr-1)%len(self.photos)=-1%3=2,此時跳到最后一張 self.curr = (self.curr-1)%len(self.photos) else: self.curr = (self.curr+1)%len(self.photos) self.lab.setPixmap(QPixmap(self.photos[self.curr])) if __name__ == '__main__': app = QApplication(sys.argv) win = MyWindow() sys.exit(app.exec())
運行結(jié)果如下:
(6)計算器
import sys from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QGridLayout, QVBoxLayout from PyQt6.QtGui import QIcon, QFont from PyQt6.QtCore import Qt class MyWindow(QWidget): def __init__(self): super().__init__() self.setWindowTitle('計算器') self.initUI() self.show() self.center() def center(self): """窗口在屏幕上居中""" win_rect = self.frameGeometry() scr_center = self.screen().availableGeometry().center() win_rect.moveCenter(scr_center) self.move(win_rect.topLeft()) def initUI(self): """初始化界面""" #lcd:液晶顯示屏(QLCDNumber) self.lcd = QLabel('0') #默認展示 self.lcd.setFont(QFont('Arial', 24, QFont.Weight.Bold)) #設置字體 self.lcd.setAlignment(Qt.AlignmentFlag.AlignRight) #右對齊 self.lcd.setStyleSheet('background-color:#000030; color:#30ff30') #設置顏色 keys = [ ['(', ')', 'Back', 'Clear'], ['7', '8', '9', '/'], ['4', '5', '6', '*'], ['1', '2', '3', '-'], ['0', '.', '=', '+'] ] grid = QGridLayout() box = QVBoxLayout() for i in range(5): for j in range(4): btn = QPushButton(keys[i][j]) btn.clicked.connect(self.on_btn) #分區(qū)設置顏色 back、clear和運算字符顏色設置與其他不同 if i == 0 and j in (2, 3): btn.setStyleSheet('background-color:#f0e0d0') elif i > 0 and j == 3: btn.setStyleSheet('background-color:#a0f0e0') elif i == 4 and j == 2: btn.setStyleSheet('background-color:#f0e0a0') else: btn.setStyleSheet('background-color:#d9e4f1') grid.addWidget(btn, i, j) box.addWidget(self.lcd) box.addSpacing(10) #設置間隔 box.addLayout(grid) self.setLayout(box) def on_btn(self): """響應按鍵""" if self.lcd.text() == 'Error': self.lcd.setText('') key = self.sender().text() if key == 'Clear': self.lcd.setText('') elif key == 'Back': self.lcd.setText(self.lcd.text()[:-1]) #回到上一步 elif key == '=': try: result = str(eval(self.lcd.text())) except: result = 'Error' self.lcd.setText(result) else: self.lcd.setText(self.lcd.text() + key) #除了計算符號和back/clear/=外,其他的數(shù)字直接拼接到末尾 if __name__ == '__main__': app = QApplication(sys.argv) win = MyWindow() sys.exit(app.exec())
運行結(jié)果如下:
(7)秒表
import sys, time from PyQt6.QtWidgets import QApplication, QWidget, QLCDNumber, QPushButton, QVBoxLayout from PyQt6.QtGui import QIcon from PyQt6.QtCore import QObject, pyqtSignal, QThread class ClockServer(QObject): """計時服務""" update_time = pyqtSignal(str) # 更新時間信號 isRun = False def run(self): """啟動服務""" while True: t0 = time.time() while self.isRun: #信號發(fā)射(執(zhí)行update_time方法)時輸出時間差,因為t0只初始化一次,這個時間差就是秒表的計時時間,'%.2f'%+數(shù)字 代表保留兩位小數(shù) self.update_time.emit('%.2f'%(time.time()-t0)) time.sleep(0.01) #每0.01s執(zhí)行一次 class MyWindow(QWidget): def __init__(self): super().__init__() self.setWindowTitle('秒表') self.setGeometry(400, 300, 240, 140) self.initUI() self.show() def initUI(self): self.lcd = QLCDNumber() #QLCDNumber:展示LCD樣式的數(shù)字 self.lcd.setDigitCount(6) #設置限制位數(shù)為6 self.lcd.display('0:00') #初始值 #設置按鈕 self.btn = QPushButton('開始') self.btn.setStyleSheet('background-color:#f0d090') self.btn.clicked.connect(self.on_btn) #設置樣式 vbox = QVBoxLayout() vbox.addWidget(self.lcd) vbox.addSpacing(5) vbox.addWidget(self.btn) self.setLayout(vbox) self.ts = ClockServer() # 創(chuàng)建計時服務,ts是自己命名的服務對象 self.ts.update_time.connect(self.lcd.display) # 連接update_time信號到液晶顯示屏的顯示函數(shù) self.thread = QThread() # 創(chuàng)建線程 self.ts.moveToThread(self.thread) # 將計時服務加到線程 self.thread.started.connect(self.ts.run) # 將計時服務的啟動方法設置為線程函數(shù) self.thread.start() # 啟動線程 def on_btn(self): """響應按鍵""" if self.btn.text() == '開始': self.ts.isRun = True self.btn.setText('停止') else: self.ts.isRun = False self.btn.setText('開始') if __name__ == '__main__': app = QApplication(sys.argv) win = MyWindow() sys.exit(app.exec())
運行結(jié)果如下:
(8)嵌入瀏覽器或其他windows應用
這里使用QAxWidget插件實現(xiàn),我們要學會怎么通過注冊表找到組件的uuid,才能通過uuid打開該組件。首先打開注冊表編輯器,找到HKEY_CLASSES_ROOT這一欄:
然后下拉找到Shell.Explorer/Shell.Explorer.1/Shell.Explorer.2可以看到這里有三個瀏覽器,任選其一即可,然后復制其uuid:
最后調(diào)用嵌入瀏覽器的代碼示例如下:
import sys from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout from PyQt6.QAxContainer import QAxWidget class MyWindow(QWidget): def __init__(self): super().__init__() self.setWindowTitle('內(nèi)嵌瀏覽器') self.setFixedSize(960, 640) widget = QAxWidget(self) #QAxWidget類是一個包裝ActiveX控件的QWidget,可以當作一個窗口類使用 #若setControl(“E:/test.doc”);直接會加載word應用打開doc文檔。 #此處的{8856F961-340A-11D0-A96B-00C04FD705A2}是Microsoft Web Browser控件的UUID,代表打開瀏覽器。 #UUID來源于注冊表HKEY_CLASSES_ROOT\Shell.Explorer.1\CLSID widget.setControl("{EAB22AC3-30C1-11CF-A7EB-0000C05BAE0B}") widget.dynamicCall('Navigate(const QString&)', 'https://cn.bing.com') #"Navigate(const QString&)"這是固定寫法,后面的https://cn.bing.com是進入的網(wǎng)址 box = QVBoxLayout(self) box.addWidget(widget ) self.center() self.show() def center(self): """窗口在屏幕上居中""" win_rect = self.frameGeometry() scr_center = self.screen().availableGeometry().center() win_rect.moveCenter(scr_center) self.move(win_rect.topLeft()) if __name__ == '__main__': app = QApplication(sys.argv) win = MyWindow() sys.exit(app.exec())
運行結(jié)果如下:
5.圖形化界面Qt Designer
為什么把這個放到最后呢?原因有二:①目前還是比較推薦自己手寫界面的,更靈活;②先學基礎(chǔ)的繪制,再看由工具轉(zhuǎn)化的圖形化代碼比較容易看懂,也比較容易在基礎(chǔ)上做改造
(1)安裝
pip install pyqt6-tools pip install pyside6
pyside6使用國內(nèi)的鏡像安裝源: pip install pyside6 -i https://pypi.douban.com/simple/
安裝完成后直接打開即可,pyside6路徑為:你的python安裝目錄\Lib\site-packages\PySide6\designer.exe
官網(wǎng)手冊:https://doc.qt.io/qt-5/qtdesigner-manual.html
(2)基礎(chǔ)控件
相信通過前面的學習,有不少控件大家已經(jīng)比較熟悉了
①Layouts:
- Vertical Layout:垂直布局
- Horizontal Layout:水平布局
- Gird Layout:柵格布局
- FormLayout:表單布局
②Spacers:
- Horizontal Spacer:水平彈簧
- Vertical Spacer:垂直彈簧
③Buttons:
- Push Button:常用按鈕
- Tool Button:工具按鈕
- Radio Button:單選框(按鈕)
- Check Box:多選框
- Command Link Button:命令連接按鈕
- Dialog Button Box:按鈕盒
④Item View(Model-Based):
- List View:列表視圖
- Tree View:樹視圖
- Table View:表格視圖
- Column View:列視圖
⑤Item Widgets(Item-Based):
- List Widget:列表部件
- Tree Widget:樹部件
- Table Widget:表格部件
⑥Containers:
- Group Box:有標題的組合框
- Scroll Area:自動滾動區(qū)
- Tool Box:抽屜控件(工具箱)
- Tab Widget:選項卡
- Stacked Widget:控件棧??丶V伙@示棧頂?shù)目丶?,開發(fā)人員可以使用raiseWidget()函數(shù)把棧中任何其他控件移到棧頂,從而實現(xiàn)控件之間的切換。
- Frame:框架。QFrame框架組件用來存放其他控件,也可用于裝飾,一般用來作為更加復雜容器的基礎(chǔ),也可以用在form中作為占用控件。
- Widget:QWidget類是所有用戶界面對象的基類,QWidget組件在創(chuàng)建時是不可見的,可以包含子控件,在刪除Widget時,子控件也一起刪除。
- MDI Area:MDI窗口顯示區(qū)。多文檔界面,主要適用于完成一項工作時需要用到多個文件,主要適用于所有工作沒有太多文件參與的情況。
- Dock Widget:??看翱凇?梢宰鳛橐粋€頂層窗口漂浮在桌面,主要作為輔助窗體出現(xiàn)在界面中,可以在很多IDE中看到??看绑w。
- QAxWidget:是一個包裝ActiveX控件的QWidget
⑦Input Widgets:
- Line Edit:單行文本編輯框
- Text Edit:多行文本編輯框
- Plain Text Edit:多行文本編輯器,用于顯示和編輯多行簡單文本(樣式同上)
- Spin Box:整數(shù)調(diào)節(jié)按鈕
⑧Double Spin Box:
- Time Edit:提供了一個部件,用于編輯時間
- Data Edit:供了一個部件,用于編輯日期
- Date/Time Edit:QDateTime類提供的一個部件,用于編輯日期和時間。
- Dial:旋轉(zhuǎn)儀表盤。應用于萬能遙控的溫度、聲音的控制、以及其他工業(yè)儀表盤等等。
- Horizontal Scroll Bar:水平卷滾條,與 QSlider 功能類似,還可以用于卷滾區(qū)域。
- Vertical Scroll Bar:垂直卷滾條,與 QSlider 功能類似,還可以用于卷滾區(qū)域。
- Horizontal Slider:水平滑動條,通過滑動來設置數(shù)值,可用于數(shù)值輸入。
- Vertical Slider:垂直滑動條,通過滑動來設置數(shù)值,可用于數(shù)值輸入。
- Key Sequence Edit:文本輸入控件。用作對快捷鍵的采集。結(jié)合其內(nèi)部的API可以實現(xiàn)對自定義快捷鍵的設置。
⑨Display Widgets:
- Label:常用的控件,用于顯示文本,顯示html超文本,放置可點擊的超鏈接,顯示圖片,動畫等等。
- Text Browser:帶有超文本導航的富文本瀏覽器,可以設置其readOnly屬性為false則可編輯,使用ui.textBrowse->document()->toPlainText()可以獲取里面的內(nèi)容出來。
- Graphics Widget:是一個擴展的基礎(chǔ)項,它在 QGraphicsItem 之上提供額外的功能。 它在很多方面與 QWidget 相似,我覺得是更靈活的大畫板。
- LCD Number:用于顯示一個LCD數(shù)字。
- Progress Bar:一個水平或垂直進度條。
- Horizontal Line:水平線
- Vertical Line:垂直線。
- OpenGL Widget:一個渲染OpenGL圖形的窗口部件。
- QQuickWidget:用來加載qml文件,用于顯示界面。
(3)使用教程
①點擊窗口控件左側(cè),即可看到全部的窗口控件
②創(chuàng)建一個MainWindow
③拖入一個控件,如表單布局FormLayout。
④雙擊表單,彈出表單布局行。⑤填入標簽文字,然后確定,即可得到一行表單,我這里添加了三行表單。
⑥保存現(xiàn)在的布局:Ctrl+S,即可保存該布局文件
⑦打開該文件,發(fā)現(xiàn)是一個標準的xml文件。
⑧使用生成的.ui文件–使用uic.loadUi
import sys from PyQt6 import QtWidgets, uic app = QtWidgets.QApplication(sys.argv) window = uic.loadUi("D:/tools/python/srcipts2023/test0628.ui") window.show() app.exec()
⑨文件轉(zhuǎn)換,進入cmd,到ui文件所在的目錄下執(zhí)行:pyuic6 -o {輸出文件名} {輸入designer設計好的.ui后綴界面文件}如:pyuic6 -o test0628.py test0628.ui
⑩pyuic工具將Ui_附加到你定義的對象名稱后面,這就是您想要導入的對象,如你創(chuàng)建的是MainWindow生成的對象默認是Ui_MainWindow。
也可以直接查看使用生成的.py文件,發(fā)現(xiàn)里面的class對象名稱就是Ui_MainWindow。
通過自定義對象MyUi繼承Ui_MainWindow類實現(xiàn)調(diào)用(為了實現(xiàn)初始化方法),最終代碼實現(xiàn)如下所示:
import sys from PyQt6 import QtWidgets, uic from test0628 import Ui_MainWindow class MyUi(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self, *args, obj=None, **kwargs): super(MyUi, self).__init__(*args, **kwargs) self.setupUi(self) app = QtWidgets.QApplication(sys.argv) window = MyUi() window.show() app.exec()
總結(jié)
到此這篇關(guān)于Python桌面應用開發(fā)實戰(zhàn)之PyQt的安裝使用的文章就介紹到這了,更多相關(guān)Python桌面應用PyQt內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python graphlib庫輕松創(chuàng)建操作分析圖形對象
Python中的graphlib庫是一個功能強大且易于使用的工具,graphlib提供了許多功能,可以幫助您創(chuàng)建、操作和分析圖形對象,本文將介紹graphlib庫的主要用法,并提供一些示例代碼和輸出來幫助您入門2024-01-01Python pydotplus安裝及可視化圖形創(chuàng)建教程
這篇文章主要為大家介紹了Python pydotplus安裝及可視化圖形創(chuàng)建教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-10-10Python編程使用matplotlib挑鉆石seaborn畫圖入門教程
這篇文章主要為大家介紹了Python編程中使用matplotlib繪圖包來挑出完美的鉆石,本篇是seaborn包畫圖使用入門篇,有需要的朋友可以借鑒參考下2021-10-10如何使用Python的xml.etree.ElementTree模塊解析和操作 XML 數(shù)據(jù)
xml.etree.ElementTree是Python標準庫中用于解析和操作XML數(shù)據(jù)的模塊,無需安裝,支持解析、創(chuàng)建、修改和查詢XML數(shù)據(jù),本文介紹如何使用Python的xml.etree.ElementTree模塊解析和操作 XML 數(shù)據(jù),感興趣的朋友跟隨小編一起看看吧2025-01-01詳解Python并發(fā)編程之創(chuàng)建多線程的幾種方法
這篇文章主要介紹了詳解Python并發(fā)編程之創(chuàng)建多線程的幾種方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-08-08python讀取查看npz/npy文件數(shù)據(jù)以及數(shù)據(jù)完全顯示方法實例
前兩天從在GitHub下載了一個代碼,其中的數(shù)據(jù)集是.npz結(jié)尾的文件,之前沒有見過不知道如何處理,下面這篇文章主要給大家介紹了關(guān)于python讀取查看npz/npy文件數(shù)據(jù)以及數(shù)據(jù)完全顯示方法的相關(guān)資料,需要的朋友可以參考下2022-04-04