我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Python桌面应用开发之PyQt

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Python桌面应用开发之PyQt

文章目录

引言:桌面应用开发三大框架介绍

Tkinter:优势是免安装、相对简单,缺点是功能少,无界面设计工具。
PyQT:使用率高,功能最为强大,代码可维护性和易读性高。
WxPython:介于Tkinter和PyQT之间,相当于压缩版QT。

总结:三种框架各有优劣,有时间可以全部学习,并不复杂。如果只选一种,这里推荐使用最主流、最保值、上限最高的PyQT。

一、PyQT介绍

Qt:Qt是一个跨平台的C++图形用户界面应用程序开发框架,目前已成为最强大,最受欢迎的跨平台GUI库之一。Qt不仅可以开发GUI程序,也可开发非GUI程序,比如控制台工具和服务程序。
PyQt:PyQt是Qt的Python封装,提供Qt类和函数的API。
PyQt6的官网:https://www.riverbankcomputing.co.uk/news
可以参考的中文手册:https://www.syrr.cn/news/415861.html?action=onClick

PyQt常用模块:
QtWidgets模块:包含应用程序类、窗口类、控件类和组件类
QtGui模块:包含和gui相关的功能,例如用于事件处理、图像处理、字体和颜色类等
QtCore模块:包含核心的非gui功能,例如线程、定时器、日期时间类、文件类等

二、安装

安装:pip install PyQt6
检查安装版本(进入python命令行):

from PyQt6.QtCore import QT_VERSION_STR, PYQT_VERSION_STRQT_VERSION_STR, PYQT_VERSION_STR

三、使用教程

(1)基础窗口

import sysfrom PyQt6.QtWidgets import QApplication, QWidget, QLabelfrom PyQt6.QtGui import QIcon, QFontfrom PyQt6.QtCore import Qt#从QWidget类派生的桌面应用程序窗口类class MyWindow(QWidget):  #QtWidgets模块:包含应用程序类、窗口类、控件类和组件类#构造函数    def __init__(self):         super().__init__() # 调用基类的构造函数        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) # 文本在标签内居中        self.show() # 显示窗口if __name__ == '__main__':    app = QApplication(sys.argv) # 创建应用程序,接收来自命令行的参数列表    win = MyWindow() # 创建窗口,这里初始化的时候不需要QWidget入参    sys.exit(app.exec()) # 应用程序主循环结束后,调用sys.exit()方法清理现场

执行后结果如下:
在这里插入图片描述

(2)分区布局窗口(类似于html中div的使用)

import sysfrom PyQt6.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QHBoxLayout, QVBoxLayoutfrom PyQt6.QtGui import QIconfrom PyQt6.QtCore import Qtclass MyWindow(QWidget):    def __init__(self):             super().__init__()        self.setWindowTitle('分区布局')        self.setGeometry(400, 300, 320, 160) # 设置窗位置和大小        lab_acc = QLabel('账号:') # 实例化标签        account = QLineEdit() #单行文本编辑框        account.setAlignment(Qt.AlignmentFlag.AlignCenter) # 文本在标签内居中        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) # 设置左侧拉伸因子        hbox_btn.addWidget(btn_ok) # 添加btn_ok控件        hbox_btn.addWidget(btn_cancel) # 添加btn_cancel控件        hbox_btn.addStretch(1) # 设置右侧拉伸因子        # 使用垂直布局管理器布局上面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())

执行后结果如下:
在这里插入图片描述

(3)栅格布局窗口(类似于html中的table)

import sysfrom PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QGridLayoutfrom PyQt6.QtGui import QIconclass MyWindow(QWidget):    def __init__(self):        super().__init__()        self.setWindowTitle('栅格布局')        self.initUI() # 初始化界面        self.show() # 显示窗口    def initUI(self):   #创建一个5*5的数组,后面会逐一放入栅格        keys = [            ['(', ')', 'Back', 'Clear'],            ['7',  '8',  '9',  '/'],             ['4',  '5',  '6',  '*'],             ['1',  '2',  '3',  '-'],             ['0',  '.',  '=',  '+']        ]          grid = QGridLayout() # 创建网格布局管理器        self.setLayout(grid) # 将网格布局管理器应用到窗口        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())

执行后结果如下:
在这里插入图片描述

(4)表单布局窗口(类似于html中的form)

import sysfrom PyQt6.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QVBoxLayout, QFormLayoutfrom PyQt6.QtGui import QIconfrom PyQt6.QtCore import Qtclass MyWindow(QWidget):    def __init__(self):        super().__init__()        self.setWindowTitle('表单布局')        self.setGeometry(400, 300, 320, 200) # 设置窗位置和大小        form = QFormLayout() # 创建表单布局管理器        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:显示平台相关的密码掩码字符,而不是实际输入的字符。        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())

执行后结果如下:
在这里插入图片描述

(5)事件函数与事件过滤器

常用的事件函数如下:
keyPressEvent(): 键盘按下事件 keyReleaseEvent(): 键盘释放事件
mouseDoubleClickEvent(): 鼠标双击事件
mouseMoveEvent(): 鼠标移动事件
mousePressEvent(): 鼠标按下事件
mouseReleaseEvent(): 鼠标释放事件
timerEvent(): 定时器事件
dragEnterEvent(): 拖拽进入当前窗口事件
dragLeaveEvent(): 拖拽离开当前窗口事件
dragMoveEvent(): 拖拽移动事件
enterEvent(): 进入窗口区域事件
leaveEvent(): 离开窗口区域事件
closeEvent(): 关闭窗口事件

示例1–事件函数:

import sysfrom PyQt6.QtWidgets import QApplication, QWidget, QLabel, QHBoxLayoutfrom PyQt6.QtCore import Qtclass MyWindow(QWidget):    def __init__(self):        super().__init__()        self.setWindowTitle('事件和事件函数')        self.setGeometry(400, 300, 320, 80)        self.initUI() # 初始化界面        self.show()        def initUI(self):        lab = QLabel('按Esc键关闭窗口')        box = QHBoxLayout()        box.addStretch(1)        box.addWidget(lab)        box.addStretch(1)        self.setLayout(box)#重写"键盘按下事件"的事件函数,指定ESC键作为触发事件的键(如果不指定就是所有键都会触发事件)    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())

执行后结果如下:
在这里插入图片描述
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 右侧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 数字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–事件过滤器:
(在刚才的基础上增加导入QEvent,添加eventFilter方法,并在最后执行installEventFilter方法)

import sysfrom PyQt6.QtWidgets import QApplication, QWidget, QLabel, QHBoxLayoutfrom PyQt6.QtCore import Qt, QEventclass MyWindow(QWidget):    def __init__(self):        super().__init__()        self.setWindowTitle('事件和事件函数')        self.setGeometry(400, 300, 320, 80)        self.initUI() # 初始化界面        self.show()            def initUI(self):        lab = QLabel('按Esc键关闭窗口')        box = QHBoxLayout()        box.addStretch(1)        box.addWidget(lab)        box.addStretch(1)        self.setLayout(box)#重写"键盘按下事件"的事件函数,指定ESC键作为触发事件的键(如果不指定就是所有键都会触发事件)    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键无法关闭窗口

(6)信号和槽

介绍:信号(signal)和槽(slot)是Qt的核心机制,也是在PyQt编程中对象之间进行通信的机制。
在创建事件循环之后,通过建立信号和槽的连接就可以实现对象之间的通信。当信号发射(emit)时,连接的槽函数将会自动执行。
示例1–使用内置的信号和槽:

import sysfrom PyQt6.QtWidgets import QPushButton, QMessageBox, QApplication, QWidgetclass 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绑定事件,点击按钮时触发        self.close()    def btn_hand(self):        widget = QWidget()        QMessageBox.information(widget, 'Pop messgae', 'OK') #触发的事件时弹出会话框if __name__ == "__main__":    app = QApplication(sys.argv)    window = Window()    window.show()    sys.exit(app.exec())

运行结果如下:
在这里插入图片描述

示例2–自定义信号和槽函数示例:

import sysfrom PyQt6.QtCore import pyqtSignal, Qtfrom PyQt6.QtWidgets import *class WinForm(QWidget):    # 自定义信号,不带参数    button_clicked_signal = pyqtSignal()     def __init__(self, parent=None):        super().__init__(parent)        self.setWindowTitle('自定义信号和槽函数示例')        self.resize(300, 150)        # 接收信号,连接到自定义槽函数        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()     # 发射信号 if __name__ == '__main__':    app = QApplication(sys.argv)    win = WinForm()    win.show()    sys.exit(app.exec())

运行结果如下:
在这里插入图片描述

示例三–结合信号和槽进行多线程操作:

import sysfrom PyQt6.QtWidgets import QApplication,QMainWindow,QWidget,QProgressBar,QVBoxLayout,QPushButtonfrom PyQt6.QtCore import QThread,QObject,pyqtSignal,Qt #线程函数 class CountSever(QObject):    _isrun = False #线程是否运行全局变量    countupdate = pyqtSignal()  #自定义信号     #构造函数    def __init__(self, interval) -> None:  #-> None 表示返回的数值类型不受限制        super().__init__()        self.interval = interval #执行间隔,初始化的时候在构造函数中指定,如self.cs1 = CountSever(100)代表每100ms执行一次     #判断单个线程是否运行    def isrun(self,value:bool):        self._isrun = value     #线程运行函数    def run(self):        while True:            pass            while self._isrun:                self.countupdate.emit()  #当线程运行时发射自定义信号                QThread.msleep(self.interval) #设置线程执行间隔  #进度条主界面,QMainWindow--顶层窗口类,重量级控件。class MainWindow(QMainWindow):    countstart = pyqtSignal(bool) #自定义信号对象    def __init__(self) -> None: #-> None 表示返回的数值类型不受限制        super().__init__()         self.init_ui()        self.setcenter() #调用下面的居中方法      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指定最小和最大步数        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按钮触发下面定义的start方法,start方法会根据当前按钮发送True/Flase的信号给countstart自定义对象,然后这个True/Flase决定了isrun的结果,决定线程是否运行        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执行一次        #自定义信号绑定下面的事件countupdate,下面的 self.progress_1.setValue(self.progress_1.value() + 1)表示执行一次进度条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函数:给多个任务各分配一个线程去执行        self.th1.started.connect(self.cs1.run) #QThread提供了QThread::started()(当线程开始时发射)和QThread::finished()(在线程运行结束后发射)两个信号        self.th1.start() #线程开始执行         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方法会根据当前按钮发送True/Flase的信号给countstart自定义对象,然后这个True/Flase决定了isrun的结果,决定线程是否运行    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)  #表示执行一次进度条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())

运行结果如下:
在这里插入图片描述

四、实战示例

(1)状态栏(追踪鼠标移动轨迹)

import sysfrom PyQt6.QtWidgets import QApplication, QMainWindow, QWidget, QLabel, QHBoxLayoutfrom PyQt6.QtGui import QIcon, QPixmapfrom PyQt6.QtCore import Qtclass MainWindow(QMainWindow):        def __init__(self):        super().__init__()        self.setWindowTitle('状态栏')        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() # 返回窗口状态栏        self.mouth_info = QLabel() # 显示鼠标坐标的标签        self.sbar.addPermanentWidget(self.mouth_info) # 将显示鼠标坐标的标签添加到状态栏        self.sbar.addPermanentWidget(QLabel('版权所有 ')) # 将版权声明添加到状态栏        self.sbar.showMessage('准备就绪', 3000) # 显示消息,3秒钟后消失        def enterEvent(self, evt):        """响应鼠标进入窗口事件"""        #QStatusBar.showMessage(str, msecs=0):显示str消息持续msecs毫秒。如果msecs为0(默认),则消息将一直显示,直到调用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())

运行结果如下:
在这里插入图片描述

(2)菜单栏

import sysfrom PyQt6.QtWidgets import QApplication, QMainWindowfrom PyQt6.QtGui import QIcon, QActionclass 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() # 返回窗口状态栏        #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('&个人权限', self)        singleAction.setStatusTip('个人权限')        singleAction.triggered.connect(lambda : print('此处响应个人权限操作'))                groupAction = QAction('&组权限', self)        groupAction.setStatusTip('组权限')        groupAction.triggered.connect(lambda : print('此处响应组权限操作'))         mb = self.menuBar()        fm = mb.addMenu('&文件')        fm.addAction(openAction)        fm.addAction(saveAction)        fm.addSeparator()        subMenu = fm.addMenu('权限')        subMenu.addAction(singleAction)        subMenu.addAction(groupAction)        fm.addSeparator()        fm.addAction(quitAction)if __name__ == '__main__':    app = QApplication(sys.argv)     win = MainWindow()    sys.exit(app.exec())

运行结果如下:
在这里插入图片描述

(3)工具栏

import sysfrom PyQt6.QtWidgets import QApplication, QMainWindow, QToolBarfrom PyQt6.QtGui import QIcon, QActionfrom PyQt6.QtCore import Qtclass 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() # 返回窗口状态栏        import sysfrom PyQt6.QtWidgets import QApplication, QMainWindow, QToolBarfrom PyQt6.QtGui import QIcon, QActionfrom PyQt6.QtCore import Qtclass 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() # 返回窗口状态栏        #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('&个人权限', self)        singleAction.setStatusTip('个人权限')        singleAction.triggered.connect(lambda : print('此处响应个人权限操作'))                groupAction = QAction('&组权限', self)        groupAction.setStatusTip('组权限')        groupAction.triggered.connect(lambda : print('此处响应组权限操作'))         mb = self.menuBar()                fm = mb.addMenu('&文件')        fm.addAction(openAction)        fm.addAction(saveAction)                fm.addSeparator() #添加分割线        subMenu = fm.addMenu('权限')        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('权限')        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('&个人权限', self)        singleAction.setStatusTip('个人权限')        singleAction.triggered.connect(lambda : print('此处响应个人权限操作'))                groupAction = QAction('&组权限', self)        groupAction.setStatusTip('组权限')        groupAction.triggered.connect(lambda : print('此处响应组权限操作'))         mb = self.menuBar()                fm = mb.addMenu('&文件')        fm.addAction(openAction)        fm.addAction(saveAction)                fm.addSeparator() #添加分割线        subMenu = fm.addMenu('权限')        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('权限')        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())

运行结果如下:
在这里插入图片描述

(4)对话框

import sys, osfrom PyQt6.QtWidgets import QApplication, QMainWindow, QWidget, QPushButton, QGridLayout, QMessageBox, QInputDialog, QColorDialog, QFileDialogfrom PyQt6.QtGui import QIconfrom PyQt6.QtCore import Qtclass MainWindow(QMainWindow):        def __init__(self):        super().__init__()        self.setWindowTitle('对话框')        self.initUI()        self.show()        def initUI(self):        grid = QGridLayout()        btns = [            ['通知消息', '警告消息', '错误消息', '确认消息', '关于'],            ['颜色选择', '保存文件', '打开文件', '选择路径', '输入']        ]                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()  #在槽函数种调用该方法可以返回信号的发出者        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, '提示', '对手认负,比赛结束。',                 QMessageBox.StandardButton.Ok                       )            self.sbar.showMessage(reply.name, 2000)        elif key == '警告消息':            reply = QMessageBox.warning(self, '警告', '不能连续提和!',                 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)  #把按钮的选择结果展示到左下角消息展示栏        elif key == '关于':            QMessageBox.about(self, '关于', '云顶之弈 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())

运行结果如下:
在这里插入图片描述

(5)相册

import sysfrom PyQt6.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QHBoxLayout, QVBoxLayoutfrom PyQt6.QtGui import QIcon, QPixmapclass 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/class="lazy" data-srcipts2023/res/1.png', 'D:/tools/python/class="lazy" data-srcipts2023/res/2.png', 'D:/tools/python/class="lazy" data-srcipts2023/res/3.png')        self.lab = QLabel()        self.lab.setPixmap(QPixmap(self.photos[self.curr])) #用label标签展示图片,默认从列表第一个图片,后面有根据按钮切换图片的方法        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)就行,这里求余总数量的作用是为了能保持循环,比如第一张前面没有照片,就会跳到最后一张            #比如第一张时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())

运行结果如下:
在这里插入图片描述

(6)计算器

import sysfrom PyQt6.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QGridLayout, QVBoxLayoutfrom PyQt6.QtGui import QIcon, QFontfrom PyQt6.QtCore import Qtclass 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)    #分区设置颜色 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/=外,其他的数字直接拼接到末尾if __name__ == '__main__':    app = QApplication(sys.argv)     win = MyWindow()    sys.exit(app.exec())

运行结果如下:
在这里插入图片描述

(7)秒表

import sys, timefrom PyQt6.QtWidgets import QApplication, QWidget, QLCDNumber, QPushButton, QVBoxLayoutfrom PyQt6.QtGui import QIconfrom PyQt6.QtCore import QObject, pyqtSignal, QThreadclass ClockServer(QObject):    """计时服务"""        update_time = pyqtSignal(str) # 更新时间信号    isRun = False        def run(self):        """启动服务"""                while True:            t0 = time.time()            while self.isRun:                #信号发射(执行update_time方法)时输出时间差,因为t0只初始化一次,这个时间差就是秒表的计时时间,'%.2f'%+数字 代表保留两位小数                self.update_time.emit('%.2f'%(time.time()-t0))                  time.sleep(0.01)    #每0.01s执行一次 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样式的数字        self.lcd.setDigitCount(6)  #设置限制位数为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() # 创建计时服务,ts是自己命名的服务对象        self.ts.update_time.connect(self.lcd.display) # 连接update_time信号到液晶显示屏的显示函数        self.thread = QThread() # 创建线程        self.ts.moveToThread(self.thread) # 将计时服务加到线程        self.thread.started.connect(self.ts.run) # 将计时服务的启动方法设置为线程函数        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())

运行结果如下:
在这里插入图片描述

(8)嵌入浏览器或其他windows应用

这里使用QAxWidget插件实现,我们要学会怎么通过注册表找到组件的uuid,才能通过uuid打开该组件。
首先打开注册表编辑器,找到HKEY_CLASSES_ROOT这一栏:
在这里插入图片描述

然后下拉找到Shell.Explorer/Shell.Explorer.1/Shell.Explorer.2可以看到这里有三个浏览器,任选其一即可,然后复制其uuid:
在这里插入图片描述

最后调用嵌入浏览器的代码示例如下:

import sysfrom PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayoutfrom PyQt6.QAxContainer import QAxWidgetclass MyWindow(QWidget):        def __init__(self):        super().__init__()        self.setWindowTitle('内嵌浏览器')        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是进入的网址        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())

运行结果如下:
在这里插入图片描述

5.图形化界面Qt Designer

为什么把这个放到最后呢?原因有二:
①目前还是比较推荐自己手写界面的,更灵活;
②先学基础的绘制,再看由工具转化的图形化代码比较容易看懂,也比较容易在基础上做改造

(1)安装

pip install pyqt6-toolspip install pyside6

pyside6使用国内的镜像安装源:pip install pyside6 -i https://pypi.douban.com/simple/

安装完成后直接打开即可,pyside6路径为:你的python安装目录\Lib\site-packages\PySide6\designer.exe

官网手册:https://doc.qt.io/qt-5/qtdesigner-manual.html

(2)基础控件

相信通过前面的学习,有不少控件大家已经比较熟悉了
①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:QT容器组件
Group Box:有标题的组合框
Scroll Area:自动滚动区
Tool Box:抽屉控件(工具箱)
Tab Widget:选项卡
Stacked Widget:控件栈。控件栈只显示栈顶的控件,开发人员可以使用raiseWidget()函数把栈中任何其他控件移到栈顶,从而实现控件之间的切换。
Frame:框架。QFrame框架组件用来存放其他控件,也可用于装饰,一般用来作为更加复杂容器的基础,也可以用在form中作为占用控件。
Widget:QWidget类是所有用户界面对象的基类,QWidget组件在创建时是不可见的,可以包含子控件,在删除Widget时,子控件也一起删除。
MDI Area:MDI窗口显示区。多文档界面,主要适用于完成一项工作时需要用到多个文件,主要适用于所有工作没有太多文件参与的情况。
Dock Widget:停靠窗口。可以作为一个顶层窗口漂浮在桌面,主要作为辅助窗体出现在界面中,可以在很多IDE中看到停靠窗体。
QAxWidget:是一个包装ActiveX控件的QWidget

⑦Input Widgets:
Line Edit:单行文本编辑框
Text Edit:多行文本编辑框
Plain Text Edit:多行文本编辑器,用于显示和编辑多行简单文本(样式同上)
Spin Box:整数调节按钮

⑧Double Spin Box:浮点数调节按钮
Time Edit:提供了一个部件,用于编辑时间
Data Edit:供了一个部件,用于编辑日期
Date/Time Edit:QDateTime类提供的一个部件,用于编辑日期和时间。
Dial:旋转仪表盘。应用于万能遥控的温度、声音的控制、以及其他工业仪表盘等等。
Horizontal Scroll Bar:水平卷滚条,与 QSlider 功能类似,还可以用于卷滚区域。
Vertical Scroll Bar:垂直卷滚条,与 QSlider 功能类似,还可以用于卷滚区域。
Horizontal Slider:水平滑动条,通过滑动来设置数值,可用于数值输入。
Vertical Slider:垂直滑动条,通过滑动来设置数值,可用于数值输入。
Key Sequence Edit:文本输入控件。用作对快捷键的采集。结合其内部的API可以实现对自定义快捷键的设置。

⑨Display Widgets:
Label:常用的控件,用于显示文本,显示html超文本,放置可点击的超链接,显示图片,动画等等。
Text Browser:带有超文本导航的富文本浏览器,可以设置其readOnly属性为false则可编辑,使用ui.textBrowse->document()->toPlainText()可以获取里面的内容出来。
Graphics Widget:是一个扩展的基础项,它在 QGraphicsItem 之上提供额外的功能。 它在很多方面与 QWidget 相似,我觉得是更灵活的大画板。
LCD Number:用于显示一个LCD数字。
Progress Bar:一个水平或垂直进度条。
Horizontal Line:水平线
Vertical Line:垂直线。
OpenGL Widget:一个渲染OpenGL图形的窗口部件。
QQuickWidget:用来加载qml文件,用于显示界面。

(3)使用教程

①点击窗口控件左侧,即可看到全部的窗口控件
在这里插入图片描述

②创建一个MainWindow
在这里插入图片描述

③拖入一个控件,如表单布局FormLayout。
在这里插入图片描述

④双击表单,弹出表单布局行。
⑤填入标签文字,然后确定,即可得到一行表单,我这里添加了三行表单。
在这里插入图片描述

⑥保存现在的布局:Ctrl+S,即可保存该布局文件
在这里插入图片描述

⑦打开该文件,发现是一个标准的xml文件。
在这里插入图片描述

⑧使用生成的.ui文件–使用uic.loadUi

import sysfrom PyQt6 import QtWidgets, uicapp = QtWidgets.QApplication(sys.argv)window = uic.loadUi("D:/tools/python/class="lazy" data-srcipts2023/test0628.ui")window.show()app.exec()

⑨文件转换,进入cmd,到ui文件所在的目录下执行:pyuic6 -o {输出文件名} {输入designer设计好的.ui后缀界面文件}
如:pyuic6 -o test0628.py test0628.ui
⑩pyuic工具将Ui_附加到你定义的对象名称后面,这就是您想要导入的对象,如你创建的是MainWindow生成的对象默认是Ui_MainWindow。
也可以直接查看使用生成的.py文件,发现里面的class对象名称就是Ui_MainWindow。
在这里插入图片描述

通过自定义对象MyUi继承Ui_MainWindow类实现调用(为了实现初始化方法),最终代码实现如下所示:

import sys from PyQt6 import QtWidgets, uicfrom test0628 import Ui_MainWindowclass 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()

来源地址:https://blog.csdn.net/tttalk/article/details/131417886

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Python桌面应用开发之PyQt

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Python如何使用Eel和HTML开发桌面应用

这篇文章主要介绍了Python使用Eel和HTML开发桌面应用问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-01-03

Golang开发桌面应用的利与弊

跨平台桌面开发中使用 go 语言的优势包括:跨平台性、高效性、并发性、强大的标准库,缺点为:gui 限制、原生 ide 支持较弱、资源消耗较高。如考虑开发跨平台文本编辑器,可以使用 go 标准库处理文件 i/o 和文本格式化,并利用第三方库
Golang开发桌面应用的利与弊
2024-04-08

python 开发GUI应用之Dabo

这几天在研究用python开发GUI应用程序,首先选择了wxpython,英文书籍wxpython in action是不错的,网上也有中文版。  在win7下安装python2.7,wxpython2.8.12.1,来个HelloWorl
2023-01-31

node.js 和HTML5开发本地桌面应用程序

HTML5让Web开发人员用纯HTML技术开发富客户端互联网应用或者甚至本地桌面应用成为了可能。HTML5可以将任何普通网站转变成Web应用。HTML5 web 应用不仅具有在桌面浏览器应用中的优势,同时在智能手机和平板中也是开发利器。 在
2022-06-04

Android之AppWidget(桌面小部件)开发浅析

什么是AppWidget AppWidget 即桌面小部件,也叫桌面控件,就是能直接显示在Android系统桌面上的小程序,先看图:图中我用黄色箭头指示的即为AppWidget,一些用户使用比较频繁的程序,可以做成AppWidget,这样能
2022-06-06

怎么使用vue和electron开发一个桌面应用

本文小编为大家详细介绍“怎么使用vue和electron开发一个桌面应用”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么使用vue和electron开发一个桌面应用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧
2023-07-05

使用NativePHP在Laravel中开发独特的桌面应用程序

在Laravel上集成NativePHP,打造独一无二的桌面应用程序随着移动应用的兴起,桌面应用程序似乎已经逐渐淡出人们的视线。然而,对于某些特定领域,特别是企业应用和专业工具,桌面应用程序仍然是必不可少的。在这种情况下,将Web应用程序转
使用NativePHP在Laravel中开发独特的桌面应用程序
2023-12-20

Golang在桌面应用程序开发中的作用与潜力

go在桌面应用程序开发中的作用:go凭借其跨平台性、并发性、简洁性和垃圾回收机制,成为桌面应用程序开发的理想选择。潜力:跨平台工具:创建可在多个平台上运行的工具。高效应用程序:利用并发性处理数据,提高性能。gui应用程序:轻松创建现代gui
Golang在桌面应用程序开发中的作用与潜力
2024-04-08

结合NativePHP和Laravel,开发创新的桌面应用程序

使用NativePHP与Laravel相融合,开发出创新的桌面应用程序在现代化的软件开发领域,Laravel是一种非常流行的PHP框架,以其简单易用、可扩展和高效的特性受到广泛关注。然而,在一些特定的项目中,我们可能需要同时结合Larave
结合NativePHP和Laravel,开发创新的桌面应用程序
2023-12-20

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录