当前位置:   article > 正文

PySide6 : Qt for Python 教程

qt for python

Python开发GUI---PySide6超详细的教程:https://zhuanlan.zhihu.com/p/673903865

  1. QWidget:基础的用户界面组件,用于构建应用程序的窗口和部件。
  2. QLabel:用于显示文本或图像的标签。
  3. QPushButton:按钮,用于触发用户交互。
  4. QLineEdit:单行文本输入框,用于接受用户的文本输入。
  5. QTextEdit:多行文本输入框,用于接受用户的多行文本输入。
  6. QComboBox:下拉框,用于选择列表中的一个选项。
  7. QCheckBox:复选框,用于表示二进制的选择状态。
  8. QRadioButton:单选按钮,用于在一组中选择一个选项。
  9. QSpinBox 和 QDoubleSpinBox:整数和浮点数的微调框,用于方便地增减数值。
  10. QSlider:滑块,用于通过拖动来选择数值。
  11. QProgressBar:进度条,用于显示操作的进度。
  12. QListWidget 和 QTreeWidget:列表框和树形控件,用于显示和管理项目列表和层次结构。
  13. QTableWidget:表格控件
  14. QTabWidget:选项卡窗口,用于将内容分组到多个选项卡页中。
  15. QFileDialog:文件对话框,用于选择文件和目录。
  16. QMenuBar 和 QMenu:菜单栏和菜单,用于组织和呈现应用程序的菜单选项。
  17. QToolBar:工具栏,用于快速访问应用程序中的常用功能。
  18. QStatusBar:状态栏,用于显示应用程序的状态信息。
  19. QMessageBox:消息框,用于显示提示、警告和错误消息。
  20. QGraphicsView 和 QGraphicsScene:用于处理 2D 图形和图形场景的组件。
  21. QCalendarWidget:日历控件,用于显示和选择日期。

PySide6 代码式教程:https://gitee.com/muzing/PySide6-Code-Tutorial
Python Qt 系列开发教程:https://blog.l0v0.com/categories/CG/Qt/Python结合Qt系列开发教程/
用 Python 编写安卓 APK:https://zhuanlan.zhihu.com/p/398126847

1、PySide6、PyQt6、PyQt5 区别

PyQt 与 PySide 基本上没有太大区别,都是在 Python 环境下的一套 Qt API库,但是 PySide 由 Qt 官方维护,不过 pyside 掉了一段时间的队,期间 pyqt 火了,导致用 pyside 的人不多。不过 pyside 的优点在于有详细的官方维护的文档,PySide6 是 PySide2 的更新版本 【Qt 5 升级到 Qt 6 后,PySide2 也跟着升级到了 PySide6 (从2直接到6)】 ,二者几乎没什么差别。它们三者之间的代码转化也非常简单。所以推荐使用 PySide6 来创建基于 Qt6 的GUI 程序。

PySide6、PyQt6 都是基于 Qt 库,Qt 是一组 C++ 库和开发工具。两者的不同主要是由于历史引起的,最初Qt的母公司是 Nokia,后来riverbank computing 公司开发了Python版本的Qt,这就是最初的PyQt,但是PyQt有两种许可协议,一种是GPLv3许可协议,另一种是需要授权的商业许可协议,GPLv3许可协议是指,如果的你的程序引用了该协议的程序,则你的程序也必须开源,如果你想要商业闭源,则必须购买该公司的商业许可协议。后来 Nokia 公司希望PyQt的GPLv3协议修改改LGPLv3协议,可以吸引更多的商业用户,但是 riverbank computing 公司拒绝了,因此,Nokia 公司单干,推出了 PySide,这就是PySide 的由来。PySide 是 Qt 开源项目的一部分,由The Qt Company维护。由于PySide是Qt的官方版本,并且与Qt的发布保持同步,因此在一些商业项目中更受欢迎。

PyQt 示例

  1. from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel
  2. app = QApplication([])
  3. window = QMainWindow()
  4. label = QLabel("Hello PyQt!")
  5. window.setCentralWidget(label)
  6. window.show()
  7. app.exec_()

PySide 示例

  1. from PySide2.QtWidgets import QApplication, QMainWindow, QLabel
  2. app = QApplication([])
  3. window = QMainWindow()
  4. label = QLabel("Hello PySide!")
  5. window.setCentralWidget(label)
  6. window.show()
  7. app.exec_()

QT官网 最新的QT版本https://www.qt.io/zh-cn/

可以看到 Qt6 是最新版本,官方维护的是Qt for python:Qt for Python
Qt for Python 提供了一系列带有演练指南的教程,以帮助新用户入门。

其中一些文档是从 C++ 移植到 Python 的,涵盖了一系列主题,从 "小部件 ( 也叫 控件" 的基本使用,到展示如何 设计应用程序的分步教程。

2、Qt Widgets:基础教程

主要概念

Widget:控件、组件、部件

  • 界面承载部分:主类(QWidget)、继承类 (QWidget的子类) (类列表,可以查看所有可用部件PySide6.QtWidgets - Qt for Python )
  • 界面框架部分 (布局)。
            主类:QLayout
            继承类:
                   QGridLayout (网格布局)
                   QBoxLayout(简单的上下布局)
                   QStackedLayout (可切换widget的布局)
                   FlowLayout
  • 界面组件部分( 其实也是 Widget 类 )
                button
                label
                等等
  • 界面样式部分
                color
                size
                font
                Icon
  • 界面交互部分
                action
                event
                signal
                slot
                connect

  概念之间关系

  • QWidget 作为页面的主体,挂载在 layout (布局) 上,layout (布局) 可以添加页面的组件,通过 action(动作,类似于点击),event(事件),signal(信号),slot(信号槽),connect(动作绑定)产生交互
  • 通过样式类,类似于 Icon(图标),大小,颜色,字体等,修改界面的细节
  • widget 上需要有 layout,layout 可以 继续添加 widget,可以一直加下去

3个 窗口基类 ( QMainWindow、QWidget、QDialog ) 的区别。

在平常 qt 开发中,通常要写自己的窗口类,那么这个窗口类该继承自哪个类呢?

  • QWidget 继承于 QObject 和 QPaintDevice
  • QDialog 和 QMainWindow 则继承于 QWidget

下面就来看下三个窗口基类的区别:

  • 1. QMainWindow: QMainWindow类 提供一个有 "中央窗口部件、菜单栏、工具栏、状态栏" 的 主应用程序窗口。QMainWindow 窗口经常被继承。QMainWindow 拥有自己的布局,可以使用 QMenuBar(菜单栏)、QToolBar(工具栏)、QStatusBar(状态栏)以及QDockWidget(悬浮窗体),布局有一个可由任何种类小窗口所占据的中心区域。

  • 2. QWidget:QWidet 类是所有用户界面对象的基类,窗口部件是用户界面的一个基本单元,它从窗口系统接收鼠标,键盘和其他消息,并在屏幕上绘制自己。一个窗口部件可以被他的父窗口或者是其他窗口挡住一部分。
  • 3. QDialog:QDialog 类是对话框窗口的基类,对话框窗口主要用于短期任务以及和用户进行短期通讯的顶级窗口,QDialog可以是模态对话框或者是非模态对话框。QDialog 支持扩展并带有返回值,可以有默认按钮。QDialog也可以有一个QSizeGrip在它的右下角,使用setSizeGripEnabled()。

    模式对话框
    阻塞同一应用程序中其它可视窗口输入的对话框。模式对话框有自己的事件循环,用户必须完成这个对话框中的交互操作,并且关闭了它之后才能访问应用程序中的其它任何窗口。模式对话框仅阻止访问与对话相关联的窗口,允许用户继续使用其它窗口中的应用程序。

    显示模态对话框最常见的方法是调用其exec()函数,当用户关闭对话框,exec()将提供一个有用的返回值,并且这时流程控制继续从调用exec()的地方进行。通常情况下,要获得对话框关闭并返回相应的值,我们连接默认按钮,例如:”确定”按钮连接到accept()槽,”取消”按钮连接到reject()槽。另外我们也可以连接done()槽,传递给它Accepted或Rejected。

    非模式对话框
    和同一个程序中其它窗口操作无关的对话框。在文字处理中的查找和替换对话框通常是非模式的,允许用户同时与应用程序的主窗口和对话框进行交互。调用show()来显示非模式对话框,并立即将控制返回给调用者。

    如果隐藏对话框后调用show()函数,对话框将显示在其原始位置,这是因为窗口管理器决定的窗户位置没有明确由程序员指定,为了保持被用户移动的对话框位置,在closeEvent()中进行处理,然后在显示之前,将对话框移动到该位置。

    半模式对话框
    调用setModal(true)或者setWindowModality(),然后show()。有别于exec(),show() 立即返回给控制调用者。

    对于进度对话框来说,调用setModal(true)是非常有用的,用户必须拥有与其交互的能力,例如:取消长时间运行的操作。如果使用show()和setModal(true)共同执行一个长时间操作,则必须定期在执行过程中调用QApplication::processEvents(),以使用户能够与对话框交互(可以参考QProgressDialog)。

QMainWindow、QWidget、QDialoh 使用原则

  • 如果需要嵌入到其他窗体中,则基于 QWidget 创建。
  • 如果是顶级对话框,则基于 QDialog 创建。
  • 如果是主窗体,则基于 QMainWindow 创建。

QMainWindow 使用示例:

  1. # -*- coding: utf-8 -*-
  2. from PySide6.QtCore import (
  3. QCoreApplication, QDate, QDateTime, QLocale,
  4. QMetaObject, QObject, QPoint, QRect,
  5. QSize, QTime, QUrl, Qt
  6. )
  7. from PySide6.QtGui import (
  8. QBrush, QColor, QConicalGradient, QCursor,
  9. QFont, QFontDatabase, QGradient, QIcon,
  10. QImage, QKeySequence, QLinearGradient, QPainter,
  11. QPalette, QPixmap, QRadialGradient, QTransform
  12. )
  13. from PySide6.QtWebEngineWidgets import QWebEngineView
  14. from PySide6.QtWidgets import (
  15. QApplication, QMainWindow, QMenuBar, QPushButton,
  16. QSizePolicy, QStatusBar, QWidget, QPlainTextEdit
  17. )
  18. class Ui_MainWindow(object):
  19. def setupUi(self, MainWindow):
  20. if not MainWindow.objectName():
  21. MainWindow.setObjectName(u"MainWindow")
  22. MainWindow.resize(700, 567)
  23. self.centralwidget = QWidget(MainWindow)
  24. self.centralwidget.setObjectName(u"centralwidget")
  25. self.plainTextEdit = QPlainTextEdit(self.centralwidget) # 添加的文本框
  26. self.plainTextEdit.setObjectName(u"plainTextEdit")
  27. self.plainTextEdit.setGeometry(QRect(90, 40, 521, 311))
  28. self.pushButton = QPushButton(self.centralwidget) # 添加的按钮
  29. self.pushButton.setObjectName(u"pushButton")
  30. self.pushButton.setGeometry(QRect(330, 410, 75, 24))
  31. MainWindow.setCentralWidget(self.centralwidget)
  32. self.menubar = QMenuBar(MainWindow)
  33. self.menubar.setObjectName(u"menubar")
  34. self.menubar.setGeometry(QRect(0, 0, 700, 22))
  35. MainWindow.setMenuBar(self.menubar)
  36. self.statusbar = QStatusBar(MainWindow)
  37. self.statusbar.setObjectName(u"statusbar")
  38. MainWindow.setStatusBar(self.statusbar)
  39. self.retranslateUi(MainWindow) # 调用下面的retranslateUi(self, MainWindow)函数。
  40. QMetaObject.connectSlotsByName(MainWindow)
  41. # setupUi
  42. def retranslateUi(self, MainWindow):
  43. MainWindow.setWindowTitle(
  44. QCoreApplication.translate("MainWindow", u"\u81ea\u5b9a\u4e49\u7684\u6807\u9898\u680f", None))
  45. self.plainTextEdit.setPlaceholderText(QCoreApplication.translate("MainWindow", u"\u8bf7\u8f93\u5165", None))
  46. self.pushButton.setText(QCoreApplication.translate("MainWindow", u"\u70b9\u51fb", None))
  47. # retranslateUi
  48. # ================== 上面为 自动生成 的代码 ============================
  49. # ================== 下面代码 使其显示出来 ============================
  50. app = QApplication()
  51. main_window = QMainWindow()
  52. auto_ui_window = Ui_MainWindow() # 实例化部件
  53. auto_ui_window.setupUi(main_window) # 调用setupUi()方法,并传入 主窗口 参数。
  54. # 给按钮绑定调用函数。
  55. # auto_ui_window.pushButton.clicked.connect(lambda x: print('点击了按钮'))
  56. auto_ui_window.pushButton.clicked.connect(lambda x: auto_ui_window.plainTextEdit.appendPlainText("点击按钮"))
  57. main_window.show()
  58. app.exec()
  59. pass

安装 PySide6、PyQt6

PySide6 库还是非常大的,推荐使用国内的镜像来下载。PySide6 只支持Python 3.6+版本,另外特别注意的是,它只支持 64 位的 Python。

使用 豆瓣源 安装:pip install -i http://pypi.doubanio.com/simple/ PySide6

安装完成后,python 安装路径下 \Lib\site-packages 里找到 designer.exe。designer 是 Python 设计里面一个非常实用的工具,使得人们编写 qt 界面可以不仅仅是使用纯代码,而可以在可视化的基础上设置,非常方便。

示例:GUI 窗口

  1. import sys
  2. import random
  3. from PySide6 import QtCore, QtWidgets, QtGui
  4. class MyWidget(QtWidgets.QWidget):
  5. def __init__(self):
  6. super().__init__()
  7. self.hello = ["Hallo Welt", "Hei maailma", "Hola Mundo", "Привет мир"]
  8. self.button = QtWidgets.QPushButton("Click me!")
  9. self.text = QtWidgets.QLabel("Hello World", alignment=QtCore.Qt.AlignCenter)
  10. self.layout = QtWidgets.QVBoxLayout(self)
  11. self.layout.addWidget(self.text)
  12. self.layout.addWidget(self.button)
  13. self.button.clicked.connect(self.magic)
  14. @QtCore.Slot()
  15. def magic(self):
  16. self.text.setText(random.choice(self.hello))
  17. if __name__ == "__main__":
  18. app = QtWidgets.QApplication([])
  19. widget = MyWidget()
  20. widget.resize(800, 600)
  21. widget.show()
  22. sys.exit(app.exec())

如果使用 PySide6 进行开发,可以不用安装 PyQt6 或者 PyQt5

pip install PyQt6
pip install pyqt6-tools

使用 designer.exe 设计界面

Qt Designer 随 PyQt5-tools 包一起安装,其安装路径在 "Python安装路径\Lib\site-packages\PyQt5\Qt5\bin" 下。若要启动 Qt Designer 可以直接到上述目录下,

  • 双击 designer.exe打开 Qt Designer;
  • 或将上述路径加入环境变量,在命令行输入designer 打开;
  • 或在 PyCharm 中将其配置为外部工具打开。

Qt Designer 生成的.ui文件(实质上是XML格式的文件)可以通过 pyuic5 工具转换成 .py 文件。

文件 ---> 新建

可以看到 templates\forms 有5个选项,这里选择 MainWindow,点击创建就进入到设计主界面。

随便设计一个界面,或者什么都不做,点击:菜单栏 ---> 文件 ---> 保存,可以看到保存文件的后缀名是 .ui,这就是设计的界面文件。

 ui文件 ---> py文件 

pyside6-uic工具可以实现 "UI文件与Python交互"。安装完 PySide 后,在 Python 解释器所在目录的 Scripts 目录 ( 我这里是 C:\Python39\Scripts\ ) 有个 pyside6-uic.exe,这个文件可以单独执行,可以把 C:\Python39\Scripts\ 加入到环境变量中,也可以把 pyside6-uic.exe 复制到一个容易找到的目录中。执行 pyside6-uic.exe --help 查看帮助

可以看到 pyside6-uic.exe 参数就是一个 ui 文件,执行命令,转换成 py 文件

或者重定向也可以:pyside6-uic untitled.ui > pyside6_gui_test.py

生成的文件内容如下:

可以看到,就一个 class,里面两个 成员方法。下面执行这个类的方法,显示 GUI 界面

方法 1:在 pyside6_gui_test.py 文件的最下面,添加如下代码:

  1. app = QApplication()
  2. main_window = QMainWindow()
  3. auto_ui_window = Ui_MainWindow() # 实例化 控件
  4. auto_ui_window.setupUi(main_window) # 调用setupUi()方法,并传入 主窗口 参数。
  5. main_window.show()
  6. app.exec()

方法 2:新建一个 py 文件,导入 pyside6_gui_test.py 里面的 Ui_MainWindow 类

  1. import sys
  2. from PySide6.QtWidgets import QApplication, QMainWindow
  3. from PySide6.QtCore import QFile
  4. from pyside6_gui_test import Ui_MainWindow
  5. class MainWindow(QMainWindow):
  6. def __init__(self):
  7. super(MainWindow, self).__init__()
  8. self.ui = Ui_MainWindow()
  9. self.ui.setupUi(self)
  10. if __name__ == "__main__":
  11. app = QApplication(sys.argv)
  12. window = MainWindow()
  13. window.show()
  14. sys.exit(app.exec())

执行结果:

Pycharm 配置 Pyside6 工具

如果嫌上面手动执行命令比较麻烦,可以把 designer 和 pyside6-uic 配置成 Pycharm 的外部工具,运行 Pycharm,设置 ---> 外部工具 ---> 点击 +,添加 Pyside6_Designer Pyside6_UIC 

  • 添加 Pyside6_Designer
            名称:Pyside6_Designer(可自己定义)
            程序:Pyside6-Designer 的安装路径。C:\Python39\Lib\site-packages\PySide6\designer.exe
            实参:不填
            工作目录: $FileDir$

  • 添加 Pyside6_UICuic 主要是用来 "将ui文件转换成py代码"
            名称:Pyside6_UIC(可自己定义)
            程序:pyside6-uic 的安装路径。C:\Python39\Scripts\pyside6-uic.exe
            实参:$FileName$ -o $FileNameWithoutExtension$.py

设计 UI文件、转py文件

通过 Qt_Designer 设计 QT界面,然后保存为 "测试.ui"文件
再通过Py_UIC会根据"测试.ui"文件生成同名的 "测试.py"文件。

如果上面 Py_UIC配置正确,生成 .py 文件很简单:

  •  .ui文件 ---> 右键 -> External Tools ---> Py_UIC,即可自动生成 py 文件,生成的.py文件 中只有一个从object 类继承的 Ui_MainWindow 的类,无法直接运行,如果想要运行,继续往下看。

运行 .py 文件,出现图形界面

ui 文件生成的 py 文件没法直接运行,有两种方法可以显示界面。

方法 1 :直接运行这个 .py文件 就能看到界面的方式,在文件末尾加上这一段代码:

  1. if __name__ == "__main__":
  2. import sys
  3. from PySide6 import QtWidgets
  4. app = QtWidgets.QApplication(sys.argv) # 创建一个QApplication,也就是你要开发的软件app
  5. MainWindow = QtWidgets.QMainWindow() # 创建一个QMainWindow,用来装载你需要的各种组件、控件
  6. # MainWindow = QtWidgets.QWidget() # 创建一个QMainWindow,用来装载你需要的各种组件、控件
  7. ui = Ui_MainWindow() # ui是你创建的ui类的实例化对象
  8. ui.setupUi(MainWindow) # 执行类中的setupUi方法,方法的参数是第二步中创建的QMainWindow
  9. MainWindow.show() # 执行QMainWindow的show()方法,显示这个QMainWindow
  10. sys.exit(app.exec_()) # 使用exit()或者点击关闭按钮退出QApplication

完整代码

  1. # -*- coding: utf-8 -*-
  2. ################################################################################
  3. ## Form generated from reading UI file '测试.ui'
  4. ##
  5. ## Created by: Qt User Interface Compiler version 6.3.0
  6. ##
  7. ## WARNING! All changes made in this file will be lost when recompiling UI file!
  8. ################################################################################
  9. from PySide6.QtCore import (
  10. QCoreApplication, QDate, QDateTime, QLocale,
  11. QMetaObject, QObject, QPoint, QRect,
  12. QSize, QTime, QUrl, Qt
  13. )
  14. from PySide6.QtGui import (
  15. QBrush, QColor, QConicalGradient, QCursor,
  16. QFont, QFontDatabase, QGradient, QIcon,
  17. QImage, QKeySequence, QLinearGradient, QPainter,
  18. QPalette, QPixmap, QRadialGradient, QTransform
  19. )
  20. from PySide6 import QtWidgets
  21. from PySide6.QtWidgets import (
  22. QApplication, QMainWindow, QMenuBar, QPushButton,
  23. QSizePolicy, QStatusBar, QWidget
  24. )
  25. class Ui_MainWindow(object):
  26. def setupUi(self, MainWindow):
  27. if not MainWindow.objectName():
  28. MainWindow.setObjectName(u"MainWindow")
  29. MainWindow.resize(800, 600)
  30. self.centralwidget = QWidget(MainWindow)
  31. self.centralwidget.setObjectName(u"centralwidget")
  32. self.pushButton = QPushButton(self.centralwidget)
  33. self.pushButton.setObjectName(u"pushButton")
  34. self.pushButton.setGeometry(QRect(150, 160, 211, 111))
  35. MainWindow.setCentralWidget(self.centralwidget)
  36. self.menubar = QMenuBar(MainWindow)
  37. self.menubar.setObjectName(u"menubar")
  38. self.menubar.setGeometry(QRect(0, 0, 800, 22))
  39. MainWindow.setMenuBar(self.menubar)
  40. self.statusbar = QStatusBar(MainWindow)
  41. self.statusbar.setObjectName(u"statusbar")
  42. MainWindow.setStatusBar(self.statusbar)
  43. self.retranslateUi(MainWindow)
  44. QMetaObject.connectSlotsByName(MainWindow)
  45. # setupUi
  46. def retranslateUi(self, MainWindow):
  47. MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
  48. self.pushButton.setText(QCoreApplication.translate("MainWindow", u"PushButton", None))
  49. # retranslateUi
  50. if __name__ == "__main__":
  51. import sys
  52. from PySide6 import QtWidgets
  53. app = QtWidgets.QApplication(sys.argv) # 创建一个QApplication,也就是你要开发的软件app
  54. MainWindow = QtWidgets.QMainWindow() # 创建一个QMainWindow,用来装载你需要的各种组件、控件
  55. # MainWindow = QtWidgets.QWidget() # 创建一个QMainWindow,用来装载你需要的各种组件、控件
  56. ui = Ui_MainWindow() # ui是你创建的ui类的实例化对象
  57. ui.setupUi(MainWindow) # 执行类中的setupUi方法,方法的参数是第二步中创建的QMainWindow
  58. MainWindow.show() # 执行QMainWindow的show()方法,显示这个QMainWindow
  59. sys.exit(app.exec_()) # 使用exit()或者点击关闭按钮退出QApplication

方法 2:在 别的文件 中 调用 这个模块。通过 继承 QtWidgets.QWidget 或者  QtWidgets.QMainWindow 来实现

  1. class MyForm(QMainWindow, Ui_MainWindow):
  2. def __init__(self):
  3. super(MyForm, self).__init__()
  4. self.setupUi(self)
  5. if __name__ == '__main__':
  6. import sys
  7. app = QApplication(sys.argv)
  8. my_form = MyForm()
  9. my_form.setWindowTitle('my_form')
  10. my_form.show()
  11. sys.exit(app.exec())
  12. pass

生成的 Python 文件只有定义主窗口以及其控件的代码,并没有程序入口的代码。为了秉持视图与逻辑分离的原则,可以再编写一个新的脚本来调用这个文件,并且创建一个窗口。这个和 方法 1 中的 右键 run 就能显示界面的方式 并不冲突,只是要在别的文件中调用这个模块。调用文件的写法( main.py ):

  1. # -*- coding: utf-8 -*-
  2. # @Author :
  3. # @File : main.py
  4. # @Software: PyCharm
  5. # @description : XXX
  6. import sys
  7. from temp import Ui_MainWindow
  8. from PyQt5 import QtWidgets
  9. # 这个类继承界面UI类
  10. class MyWindow1(QtWidgets.QWidget, Ui_MainWindow):
  11. def __init__(self):
  12. super(MyWindow1, self).__init__()
  13. self.setupUi(self)
  14. # 这个类继承界面UI类
  15. class MyWindow2(QtWidgets.QMainWindow, Ui_MainWindow):
  16. def __init__(self):
  17. super(MyWindow2, self).__init__()
  18. self.setupUi(self)
  19. # 调用show
  20. if __name__ == "__main__":
  21. app = QtWidgets.QApplication(sys.argv)
  22. form_1 = MyWindow1()
  23. form_1.setWindowTitle('form_1')
  24. form_1.show()
  25. form_2 = MyWindow2()
  26. form_2.setWindowTitle('form_2')
  27. form_2.show()
  28. sys.exit(app.exec_())

被调用文件( temp.py )和上面 temp.py 文件一样。承了Ui_MainWindow类,使用其构造方法构造主窗口,并定义了程序的入口,通过创建 QApplication 对象来创建Qt窗口

程序运行截图:

示例:QtWidgets 应用程序

https://doc.qt.io/qtforpython/tutorials/basictutorial/widgets.html

与任何其他编程框架一样,从传统的 “Hello World” 程序开始。以下是 PySide6 中 Hello World 应用程序的简单示例:

  1. import sys
  2. from PySide6.QtWidgets import QApplication, QLabel
  3. app = QApplication(sys.argv) # app = QApplication([])
  4. label = QLabel("Hello World!")
  5. # This HTML approach will be valid too!
  6. label = QLabel("<font color=red size=40>Hello World!</font>")
  7. label.resize(300, 150)
  8. label.show()
  9. app.exec()

解释:

  • 使用 PySide6 的 控件 应用程序,必须始终从 PySide6.QtWidgets 模块导入适当的类开始。
  • 导入后,首先创建一个 QApplication 实例。由于 Qt 可以从命令行接收参数,所以可以将所有参数传递给 QApplication 对象。如果不需要传递任何参数则可以传递 []
  • 创建应用程序对象后,我们创建了一个 QLabel 对象。QLabel是一个可以呈现文本(简单或丰富,如 html)和 图像的 控件
  • 创建完标签后,调用标签的 show() 方法 进行显示。
  • 最后,调用 app.exec()进入 Qt 主循环,开始执行Qt代码

所有的控件 都是 PySide6.QtWidgets 的 子类

按钮

https://doc.qt.io/qtforpython/tutorials/basictutorial/clickablebutton.html

展示如何使用 Qt for Python 处理 信号和插槽。Signals and slots 是 Qt 的一项功能,它可以让您的 图形控件 与其他 图形控件  或您的 python 代码进行通信。

应用程序创建了一个按钮来记录单击的 按钮,你好!每次单击时都会向 python 控制台发送消息。

  1. # -*- coding: utf-8 -*-
  2. import sys
  3. from PySide6.QtWidgets import QApplication, QPushButton
  4. from PySide6.QtCore import Slot
  5. @Slot()
  6. def say_hello():
  7. print("Button clicked, Hello!")
  8. if __name__ == '__main__':
  9. # 创建 Qt Application
  10. app = QApplication(sys.argv)
  11. # 创建 一个按钮控件
  12. button = QPushButton("Click me")
  13. # 按钮的 "信号clicked" 连接到 "槽函数say_hello"
  14. button.clicked.connect(say_hello)
  15. button.show()
  16. # Run the main Qt loop
  17. app.exec()
  18. pass

@Slot () 是一个将 函数 标识为 槽 的装饰器。

示例:

  1. # -*- coding: utf-8 -*-
  2. import sys
  3. from PySide6 import QtCore, QtWidgets, QtGui
  4. def main():
  5. app = QtWidgets.QApplication([])
  6. widget = QtWidgets.QWidget()
  7. def show_msg():
  8. QtWidgets.QMessageBox.information(widget, '信息提示框', 'Ok 弹出测试信息')
  9. btn = QtWidgets.QPushButton('测试点击按钮', widget)
  10. btn.clicked.connect(show_msg)
  11. widget.resize(500, 500)
  12. widget.show()
  13. sys.exit(app.exec())
  14. pass
  15. if __name__ == "__main__":
  16. main()
  17. pass

示例:

  1. # -*- coding: utf-8 -*-
  2. import sys
  3. import random
  4. from PySide6 import QtCore, QtWidgets, QtGui
  5. def main():
  6. my_app = QtWidgets.QApplication() # 实例化一个应用
  7. main_window = QtWidgets.QMainWindow() # 实例化一个主窗口
  8. main_window.resize(500, 400) # 设置窗口大小
  9. main_window.move(300, 310) # 移动窗口距离屏幕左上角的位置。
  10. main_window.setWindowTitle('这是标题') # 设置窗口标题。
  11. # 在主窗口中添加一个文本框,并指定父窗口 是 main_window
  12. text_edit = QtWidgets.QPlainTextEdit(main_window)
  13. text_edit.setPlaceholderText('默认输入内容……') # 设置文本框内的默认内容。
  14. text_edit.move(10, 25)
  15. text_edit.resize(300, 350)
  16. btn_1 = QtWidgets.QPushButton('btn_1', main_window) # 在主窗口中添加一个按钮
  17. btn_1.move(350, 50)
  18. btn_1.clicked.connect(lambda x: text_edit.appendPlainText("点击按钮次")) # 给按钮绑定调用函数。
  19. btn_2 = QtWidgets.QPushButton('btn_2', main_window) # 在主窗口中添加一个按钮
  20. def say_hello():
  21. text_edit.appendPlainText("Button clicked, Hello!")
  22. btn_2.clicked.connect(say_hello)
  23. btn_2.move(100, 100)
  24. main_window.show() # 显示窗口
  25. my_app.exec() # 使窗口保持显示状态。
  26. if __name__ == "__main__":
  27. main()
  28. pass

示例:

  1. # -*- coding: utf-8 -*-
  2. import sys
  3. import random
  4. from PySide6 import QtCore, QtWidgets, QtGui
  5. class MyWidget(QtWidgets.QWidget):
  6. def __init__(self):
  7. super().__init__()
  8. self.hello = ["Hello 111", "Hello 222", "Hello 333"]
  9. self.button = QtWidgets.QPushButton("Click me!")
  10. self.text = QtWidgets.QLabel("Hello World")
  11. self.text.setAlignment(QtCore.Qt.AlignCenter)
  12. self.layout = QtWidgets.QVBoxLayout(self)
  13. self.layout.addWidget(self.text)
  14. self.layout.addWidget(self.button)
  15. self.button.clicked.connect(self.magic)
  16. @QtCore.Slot()
  17. def magic(self):
  18. self.text.setText(random.choice(self.hello))
  19. def main():
  20. app = QtWidgets.QApplication([])
  21. widget = MyWidget()
  22. widget.resize(800, 600)
  23. widget.show()
  24. sys.exit(app.exec())
  25. if __name__ == "__main__":
  26. main()
  27. pass

信号、插槽

https://doc.qt.io/qtforpython/tutorials/basictutorial/signals_and_slots.html

信号事件槽函数事件处理函数。槽 用于建立 "事件" 和 "槽函数" 的关联关系。

由于 Qt 的性质,QObjects 需要一种通信方式,这就是这种机制成为Qt 核心特性的原因。

信号与插槽简单比喻:可以想象和家里的灯互动,来类比和理解 Signal 和 Slots 。当你移动电灯开关(信号)时,您会得到一个结果,可能是您的灯泡打开/关闭(插槽)。

在开发界面时,您可以通过单击按钮的效果来获得一个真实的示例:“单击”将是信号,而插槽将是单击该按钮时发生的情况,例如关闭窗口,保存文档等.

所有继承自 QObject 的子类,以及其子类之一的 QWidget类 都可以包含信号和插槽。当一个对象以可能对其他对象感兴趣的方式改变其状态时,信号由对象发出。这就是对象进行通信的全部内容

可以将任意数量的信号连接到单个插槽,并且可以将信号连接到任意数量的插槽。甚至可以将一个信号直接连接到另一个信号。(这将在第一个信号发出时立即发出第二个信号。)

Qt 的 控件 有许多预定义的信号和槽。例如, QAbstractButton(Qt 中按钮的基类)有一个clicked() 信号,QLineEdit(单行输入字段)有一个名为 clear() 的槽。因此,可以通过在QLineEdit 的右侧 放置一个 QToolButton 并将其 clicked() 信号连接到插槽 "clear()" 来实现带有清除文本的按钮的文本输入字段。这是使用信号的connect()方法完成的:

  1. button = QToolButton()
  2. line_edit = QLineEdit()
  3. button.clicked.connect(line_edit.clear)

connect() 返回一个 QMetaObject.Connection 对象,可以与 disconnect() 方法一起使用来断开连接。信号也可以连接到自由函数:

  1. import sys
  2. from PySide6.QtWidgets import QApplication, QPushButton
  3. def func():
  4. print("The 'function' has been called!")
  5. app = QApplication()
  6. button = QPushButton("Call function")
  7. button.clicked.connect(func)
  8. button.show()
  9. sys.exit(app.exec())

信号 类

在 Python 中编写类时,信号被声明为 class 的类级变量QtCore.Signal()。基于 QWidget 的按钮控件发送 clicked() 信号 伪代码:

  1. from PySide6.QtCore import Qt, Signal
  2. from PySide6.QtWidgets import QWidget
  3. class Button(QWidget):
  4. clicked = Signal(Qt.MouseButton)
  5. ...
  6. def mousePressEvent(self, event):
  7. self.clicked.emit(event.button())

Signal 的 构造函数 接受一个元组或 Python 类型和 C 类型的列表:

  1. signal1 = Signal(int) # Python types
  2. signal2 = Signal(QUrl) # Qt Types
  3. signal3 = Signal(int, str, int) # more than one type
  4. signal4 = Signal((float,), (QDate,)) # optional types

Signal 的 构造函数 还可以接收 name 定义信号名称的命名参数。如果没有传递任何内容,则新信号将与分配给它的变量具有相同的名称。

  1. # TODO
  2. signal5 = Signal(int, name='rangeChanged')
  3. # ...
  4. rangeChanged.emit(...)

另一个有用的选项 Signal 是参数名称,对于 QML 应用程序按名称引用发出的值很有用:

sumResult = Signal(int, arguments=['sum'])
  1. Connections {
  2. target: ...
  3. function onSumResult(sum) {
  4. // do something with 'sum'
  5. }

插槽 类

QObject 派生类中的插槽应由装饰器 @QtCore.Slot() 指示 。同样,要定义签名,只需传递与类相似的 QtCore.Signal() 类型。

  1. @Slot(str)
  2. def slot_function(self, s):
  3. ...

Slot() 也接受一个 name 和一个 result 关键字。result关键字定义将返回的类型,可以是 C 或 Python 类型。关键字的 name 行为方式为 Signal()。如果没有作为名称传递,则新插槽将与正在装饰的函数具有相同的名称。

重载不同类型的 信号 和 槽

实际上可以使用具有不同参数类型列表的相同名称的信号和槽。这是 Qt 5 的遗留问题,不推荐用于新代码。在 Qt 6 中,不同类型的信号具有不同的名称。

  1. import sys
  2. from PySide6.QtWidgets import QApplication, QPushButton
  3. from PySide6.QtCore import QObject, Signal, Slot
  4. class Communicate(QObject):
  5. # create two new signals on the fly: one will handle
  6. # int type, the other will handle strings
  7. speak = Signal((int,), (str,))
  8. def __init__(self, parent=None):
  9. super(Communicate, self).__init__(parent)
  10. self.speak[int].connect(self.say_something)
  11. self.speak[str].connect(self.say_something)
  12. # define a new slot that receives a C 'int' or a 'str'
  13. # and has 'say_something' as its name
  14. @Slot(int)
  15. @Slot(str)
  16. def say_something(self, arg):
  17. if isinstance(arg, int):
  18. print("This is a number:", arg)
  19. elif isinstance(arg, str):
  20. print("This is a string:", arg)
  21. if __name__ == "__main__":
  22. app = QApplication(sys.argv)
  23. someone = Communicate()
  24. # emit 'speak' signal with different arguments.
  25. # we have to specify the str as int is the default
  26. someone.speak.emit(10)
  27. someone.speak[str].emit("Hello everybody!")

示例:获取网页 html

https://www.52pojie.cn/thread-1570807-1-1.html

  1. import sys
  2. import httpx
  3. from PySide6.QtCore import *
  4. from PySide6.QtWidgets import *
  5. class HtmlWorker(QThread):
  6. completed = Signal(httpx.Response)
  7. failed = Signal(object)
  8. def set_url(self, url):
  9. self.url = url
  10. def run(self):
  11. try:
  12. resp = httpx.get(self.url, follow_redirects=True)
  13. except BaseException as be:
  14. self.failed.emit(be)
  15. else:
  16. self.completed.emit(resp)
  17. class MainWindow(QMainWindow):
  18. def __init__(self):
  19. super(MainWindow, self).__init__()
  20. self.output = None
  21. self.btn = None
  22. self.edit = None
  23. self.setWindowTitle('PySide6 Demo')
  24. rect = self.screen().geometry()
  25. size = self.size()
  26. self.setGeometry(QStyle.alignedRect(Qt.LayoutDirection.LeftToRight, Qt.AlignCenter, size, rect))
  27. self.htmlWorker = HtmlWorker()
  28. self.htmlWorker.completed.connect(self.show_message)
  29. self.htmlWorker.failed.connect(self.show_error)
  30. # ui
  31. widget = QWidget()
  32. self.setCentralWidget(widget)
  33. layout = QVBoxLayout()
  34. layout.addLayout(self.set_input_layout())
  35. layout.addWidget(self.set_output_widget())
  36. widget.setLayout(layout)
  37. def set_input_layout(self):
  38. self.edit = QLineEdit()
  39. self.btn = QPushButton('&Show Html')
  40. layout = QHBoxLayout()
  41. layout.addWidget(self.edit)
  42. layout.addWidget(self.btn)
  43. self.edit.returnPressed.connect(self.btn.click)
  44. self.btn.clicked.connect(self.fetch_html)
  45. return layout
  46. def set_output_widget(self):
  47. self.output = QTextEdit()
  48. return self.output
  49. @Slot()
  50. def fetch_html(self):
  51. if self.htmlWorker.isRunning():
  52. return
  53. url = self.edit.text()
  54. if not url:
  55. return
  56. self.output.clear()
  57. if not url.startswith('http'):
  58. url = 'https://' + url
  59. self.htmlWorker.set_url(url)
  60. self.htmlWorker.start()
  61. @Slot(httpx.Response)
  62. def show_message(self, resp):
  63. self.output.setPlainText(resp.text)
  64. @Slot(object)
  65. def show_error(self, err):
  66. QMessageBox.warning(self, 'error', str(err))
  67. if __name__ == '__main__':
  68. app = QApplication(sys.argv)
  69. win = MainWindow()
  70. win.show()
  71. sys.exit(app.exec())

菜单栏

示例:

  1. # -*- coding: utf-8 -*-
  2. """PySide6 Active Qt Viewer example"""
  3. import sys
  4. from PySide6.QtAxContainer import QAxSelect, QAxWidget
  5. from PySide6.QtGui import QAction
  6. from PySide6.QtWidgets import (
  7. QApplication, QDialog,
  8. QMainWindow, QMessageBox, QToolBar
  9. )
  10. class MainWindow(QMainWindow):
  11. def __init__(self):
  12. super().__init__()
  13. toolBar = QToolBar()
  14. self.addToolBar(toolBar)
  15. fileMenu = self.menuBar().addMenu("&File")
  16. loadAction = QAction("Load...", self, shortcut="Ctrl+L", triggered=self.load)
  17. fileMenu.addAction(loadAction)
  18. toolBar.addAction(loadAction)
  19. exitAction = QAction("E&xit", self, shortcut="Ctrl+Q", triggered=self.close)
  20. fileMenu.addAction(exitAction)
  21. aboutMenu = self.menuBar().addMenu("&About")
  22. aboutQtAct = QAction("About &Qt", self, triggered=qApp.aboutQt)
  23. aboutMenu.addAction(aboutQtAct)
  24. self.axWidget = QAxWidget()
  25. self.setCentralWidget(self.axWidget)
  26. def load(self):
  27. axSelect = QAxSelect(self)
  28. if axSelect.exec() == QDialog.Accepted:
  29. clsid = axSelect.clsid()
  30. if not self.axWidget.setControl(clsid):
  31. QMessageBox.warning(self, "AxViewer", f"Unable to load {clsid}.")
  32. if __name__ == '__main__':
  33. app = QApplication(sys.argv)
  34. mainWin = MainWindow()
  35. availableGeometry = mainWin.screen().availableGeometry()
  36. mainWin.resize(availableGeometry.width() / 3, availableGeometry.height() / 2)
  37. mainWin.show()
  38. sys.exit(app.exec())

创建 对话框 应用程序

https://doc.qt.io/qtforpython/tutorials/basictutorial/dialog.html

创建一个自定义类 Form ,并继承 QDialog 。添加 __init()__方法,然后调用 QDialog 的 init 方法。 setWindowTitle() 方法只是设置对话框窗口的标题。在 main()中,创建一个Form 对象,然后调用 show() 方法 进行显示

  1. # -*- coding: utf-8 -*-
  2. import sys
  3. from PySide6 import QtCore, QtWidgets, QtGui
  4. class Form(QtWidgets.QDialog):
  5. def __init__(self, parent=None):
  6. super(Form, self).__init__(parent)
  7. self.setWindowTitle("My Form")
  8. # 创建组件
  9. self.edit = QtWidgets.QLineEdit("Write my name here..")
  10. self.button = QtWidgets.QPushButton("Show Greetings")
  11. # 连接 greetings 槽函数 和 按钮单击信号
  12. self.button.clicked.connect(self.btn_clicked)
  13. # 创建布局并添加组件
  14. self.layout = QtWidgets.QVBoxLayout(self) # 指定布局的 父窗口是当前窗口
  15. # 也可以这样设置布局,因为 Form 继承自 QtWidgets.QDialog
  16. # QtWidgets 有个 setLayout 方法设置布局
  17. # layout111 = QtWidgets.QVBoxLayout()
  18. # self.setLayout(layout111)
  19. self.layout.addWidget(self.edit)
  20. self.layout.addWidget(self.button)
  21. def btn_clicked(self):
  22. print(f"Hello {self.edit.text()}")
  23. if __name__ == '__main__':
  24. app = QtWidgets.QApplication([])
  25. my_form = Form()
  26. my_form.resize(800, 600)
  27. my_form.show()
  28. sys.exit(app.exec())
  29. pass

使用 表格控件 显示数据

https://doc.qt.io/qtforpython/tutorials/basictutorial/tablewidget.html

如果要显示排列在表格中的数据,可以使用 aQTableWidget来执行此操作,而无需处理太多配置。

注意:使用 aQTableWidget并不是在表格中显示信息的唯一路径。还可以创建数据模型,然后使用QTableView显示。

  1. # -*- coding: utf-8 -*-
  2. import sys
  3. from PySide6 import QtWidgets
  4. from PySide6.QtGui import QColor
  5. colors = [
  6. ("Red", "#FF0000"),
  7. ("Green", "#00FF00"),
  8. ("Blue", "#0000FF"),
  9. ("Black", "#000000"),
  10. ("White", "#FFFFFF"),
  11. ("Electric Green", "#41CD52"),
  12. ("Dark Blue", "#222840"),
  13. ("Yellow", "#F9E56d")
  14. ]
  15. def get_rgb_from_hex(code):
  16. code_hex = code.replace("#", "")
  17. rgb = tuple(int(code_hex[i:i + 2], 16) for i in (0, 2, 4))
  18. return QColor.fromRgb(rgb[0], rgb[1], rgb[2])
  19. def main():
  20. app = QtWidgets.QApplication()
  21. table = QtWidgets.QTableWidget()
  22. table.setRowCount(len(colors))
  23. table.setColumnCount(len(colors[0]) + 1)
  24. table.setHorizontalHeaderLabels(["Name", "Hex Code", "Color"])
  25. for i, (name, code) in enumerate(colors):
  26. item_name = QtWidgets.QTableWidgetItem(name)
  27. item_code = QtWidgets.QTableWidgetItem(code)
  28. item_color = QtWidgets.QTableWidgetItem()
  29. item_color.setBackground(get_rgb_from_hex(code))
  30. table.setItem(i, 0, item_name)
  31. table.setItem(i, 1, item_code)
  32. table.setItem(i, 2, item_color)
  33. table.resize(500, 500)
  34. table.show()
  35. sys.exit(app.exec())
  36. if __name__ == '__main__':
  37. main()
  38. pass

使用 树 控件 显示数据

https://doc.qt.io/qtforpython/tutorials/basictutorial/treewidget.html

注意:使用 aQTreeWidget并不是在树中显示信息的唯一路径。还可以创建数据模型,然后使用 QTreeView 显示。

  1. # -*- coding: utf-8 -*-
  2. import sys
  3. from PySide6 import QtWidgets
  4. def main():
  5. data = {
  6. "Project A": ["file_a.py", "file_a.txt", "something.xls"],
  7. "Project B": ["file_b.csv", "photo.jpg"],
  8. "Project C": []
  9. }
  10. app = QtWidgets.QApplication()
  11. tree = QtWidgets.QTreeWidget()
  12. tree.setColumnCount(2)
  13. tree.setHeaderLabels(["Name", "Type"])
  14. items = []
  15. for key, values in data.items():
  16. item = QtWidgets.QTreeWidgetItem([key])
  17. for value in values:
  18. ext = value.split(".")[-1].upper()
  19. child = QtWidgets.QTreeWidgetItem([value, ext])
  20. item.addChild(child)
  21. items.append(item)
  22. tree.insertTopLevelItems(0, items)
  23. tree.show()
  24. sys.exit(app.exec())
  25. if __name__ == '__main__':
  26. main()
  27. pass

使用 Designer 或 QtCreator 的.ui文件与QUiLoader和pyside6-uic 

https://doc.qt.io/qtforpython/tutorials/basictutorial/uifiles.html

使用 Qt Designer 可以为 Qt for Python 项目创建基于 Qt Widgets 的图形界面。 Qt Designer是一个图形 UI 设计工具,它可以作为独立的二进制文件 ( pyside6-designer) 使用,也可以嵌入到 Qt Creator IDE中。使用 Qt Designer 描述了 它在Qt Creator中的使用。

设计好的图形界面存储在.ui文件中,这是一种基于 XML 的格式。pyside6-uic 工具将在项目构建时将其转换为填充小部件实例的 Python 或 C++ 代码。

文件 mainwindow.ui如下所示

下面说明如何在 Python 中使用这个 ui 文件。

方法 1: ui代码 转成 Python代码

与UI 文件 交互的标准方法是 " 生成 Python 类 "。这要归功于pyside6-uic工具。

在控制台上运行以下命令:pyside6-uic mainwindow.ui > ui_mainwindow.py

命令的所有输出重定向到一个名为 ui_mainwindow.py 的文件,该文件将直接导入:from ui_mainwindow import Ui_MainWindow

完整代码:

  1. import sys
  2. from PySide6.QtWidgets import QApplication, QMainWindow
  3. from PySide6.QtCore import QFile
  4. from ui_mainwindow import Ui_MainWindow
  5. class MainWindow(QMainWindow):
  6. def __init__(self):
  7. super(MainWindow, self).__init__()
  8. self.ui = Ui_MainWindow()
  9. self.ui.setupUi(self)
  10. if __name__ == "__main__":
  11. app = QApplication(sys.argv)
  12. window = MainWindow()
  13. window.show()
  14. sys.exit(app.exec())

self.ui = Ui_MainWindow()
self.ui.setupUi(self)

这两行代码 负责从 UI 文件加载生成的 python 类

每次对UI 文件进行更改时,都必须再次运行pyside6-uic。

示例:

  1. # -*- coding: utf-8 -*-
  2. from PySide6.QtCore import (
  3. QCoreApplication, QDate, QDateTime, QLocale,
  4. QMetaObject, QObject, QPoint, QRect,
  5. QSize, QTime, QUrl, Qt
  6. )
  7. from PySide6.QtGui import (
  8. QBrush, QColor, QConicalGradient, QCursor,
  9. QFont, QFontDatabase, QGradient, QIcon,
  10. QImage, QKeySequence, QLinearGradient, QPainter,
  11. QPalette, QPixmap, QRadialGradient, QTransform
  12. )
  13. from PySide6.QtWebEngineWidgets import QWebEngineView
  14. from PySide6.QtWidgets import (
  15. QApplication, QMainWindow, QMenuBar, QPushButton,
  16. QSizePolicy, QStatusBar, QWidget, QPlainTextEdit
  17. )
  18. class Ui_MainWindow(object):
  19. def setupUi(self, MainWindow):
  20. if not MainWindow.objectName():
  21. MainWindow.setObjectName(u"MainWindow")
  22. MainWindow.resize(700, 567)
  23. self.centralwidget = QWidget(MainWindow)
  24. self.centralwidget.setObjectName(u"centralwidget")
  25. self.plainTextEdit = QPlainTextEdit(self.centralwidget) # 添加的文本框
  26. self.plainTextEdit.setObjectName(u"plainTextEdit")
  27. self.plainTextEdit.setGeometry(QRect(90, 40, 521, 311))
  28. self.pushButton = QPushButton(self.centralwidget) # 添加的按钮
  29. self.pushButton.setObjectName(u"pushButton")
  30. self.pushButton.setGeometry(QRect(330, 410, 75, 24))
  31. MainWindow.setCentralWidget(self.centralwidget)
  32. self.menubar = QMenuBar(MainWindow)
  33. self.menubar.setObjectName(u"menubar")
  34. self.menubar.setGeometry(QRect(0, 0, 700, 22))
  35. MainWindow.setMenuBar(self.menubar)
  36. self.statusbar = QStatusBar(MainWindow)
  37. self.statusbar.setObjectName(u"statusbar")
  38. MainWindow.setStatusBar(self.statusbar)
  39. self.retranslateUi(MainWindow) # 调用下面的retranslateUi(self, MainWindow)函数。
  40. QMetaObject.connectSlotsByName(MainWindow)
  41. # setupUi
  42. def retranslateUi(self, MainWindow):
  43. MainWindow.setWindowTitle(
  44. QCoreApplication.translate("MainWindow", u"\u81ea\u5b9a\u4e49\u7684\u6807\u9898\u680f", None))
  45. self.plainTextEdit.setPlaceholderText(QCoreApplication.translate("MainWindow", u"\u8bf7\u8f93\u5165", None))
  46. self.pushButton.setText(QCoreApplication.translate("MainWindow", u"\u70b9\u51fb", None))
  47. # retranslateUi
  48. # ================== 上面为 自动生成 的代码 ============================
  49. # ================== 下面代码 使其显示出来 ============================
  50. app = QApplication()
  51. main_window = QMainWindow()
  52. auto_ui_window = Ui_MainWindow() # 实例化部件
  53. auto_ui_window.setupUi(main_window) # 调用setupUi()方法,并传入 主窗口 参数。
  54. # 给按钮绑定调用函数。
  55. # auto_ui_window.pushButton.clicked.connect(lambda x: print('点击了按钮'))
  56. auto_ui_window.pushButton.clicked.connect(lambda x: auto_ui_window.plainTextEdit.appendPlainText("点击按钮"))
  57. main_window.show()
  58. app.exec()
  59. pass

方法 2:直接加载 ui 代码

要直接加载 UI 文件,需要 QtUiTools 模块中的一个类:from PySide6.QtUiTools import QUiLoader

QUiLoader 可以动态加载 ui文件并立即使用它:

  1. # -*- coding: utf-8 -*-
  2. from PySide6.QtCore import QFile, QIODevice
  3. from PySide6.QtUiTools import QUiLoader
  4. ui_file = QFile("mainwindow.ui")
  5. ui_file.open(QFile.ReadOnly)
  6. loader = QUiLoader()
  7. window = loader.load(ui_file)
  8. window.show()

完整代码:

  1. # -*- coding: utf-8 -*-
  2. import sys
  3. from PySide6.QtUiTools import QUiLoader
  4. from PySide6.QtWidgets import QApplication
  5. from PySide6.QtCore import QFile, QIODevice
  6. if __name__ == "__main__":
  7. app = QApplication(sys.argv)
  8. ui_file_name = "mainwindow.ui"
  9. ui_file = QFile(ui_file_name)
  10. if not ui_file.open(QIODevice.ReadOnly):
  11. print(f"Cannot open {ui_file_name}: {ui_file.errorString()}")
  12. sys.exit(-1)
  13. loader = QUiLoader()
  14. window = loader.load(ui_file)
  15. ui_file.close()
  16. if not window:
  17. print(loader.errorString())
  18. sys.exit(-1)
  19. window.show()
  20. sys.exit(app.exec())

使用.qrc文件

https://doc.qt.io/qtforpython/tutorials/basictutorial/qrcfiles.html

Qt 资源系统是一种在应用程序中存储二进制文件的机制。这些文件将被嵌入到应用程序中,并且可以 QFile通过QIcon使用QPixmap 以:/。最常见的用途是自定义图像、图标、字体等。

在本教程中,将自定义图像加载为按钮图标。以 Qt 中的多媒体播放器示例。

将有关资源的信息添加到.qrc 文件中:

把 图标 添加到 

  1. </ui>
  2. <!DOCTYPE RCC><RCC version="1.0">
  3. <qresource>
  4. <file>icons/play.png</file>
  5. <file>icons/pause.png</file>
  6. <file>icons/stop.png</file>
  7. <file>icons/previous.png</file>
  8. <file>icons/forward.png</file>
  9. </qresource>
  10. </RCC>

生成 Python 文件

现在 icons.qrc 文件准备好了,使用 pyside6-rcc 工具生成一个 Python 类。

运行命令:pyside6-rcc icons.rc -o rc_icons.py

-o 选项允许您指定输出文件名,在本例中为rc_icons.py。

修改代码:

from PySide6.QtGui import QIcon, QKeySequence
playIcon = self.style().standardIcon(QStyle.SP_MediaPlay)
previousIcon = self.style().standardIcon(QStyle.SP_MediaSkipBackward)
pauseIcon = self.style().standardIcon(QStyle.SP_MediaPause)
nextIcon = self.style().standardIcon(QStyle.SP_MediaSkipForward)
stopIcon = self.style().standardIcon(QStyle.SP_MediaStop)

改为

  1. from PySide6.QtGui import QIcon, QKeySequence, QPixmap
  2. playIcon = QIcon(QPixmap(":/icons/play.png"))
  3. previousIcon = QIcon(QPixmap(":/icons/previous.png"))
  4. pauseIcon = QIcon(QPixmap(":/icons/pause.png"))
  5. nextIcon = QIcon(QPixmap(":/icons/forward.png"))
  6. stopIcon = QIcon(QPixmap(":/icons/stop.png"))

这可确保使用新图标而不是应用程序主题提供的默认图标。请注意,这些行不是连续的,而是位于文件的不同部分。在所有导入之后,在主 Python 文件的顶部添加以下导入:import rc_icons

类 的构造函数:

  1. def __init__(self):
  2. super(MainWindow, self).__init__()
  3. self.playlist = QMediaPlaylist()
  4. self.player = QMediaPlayer()
  5. toolBar = QToolBar()
  6. self.addToolBar(toolBar)
  7. fileMenu = self.menuBar().addMenu("&File")
  8. openAction = QAction(QIcon.fromTheme("document-open"),
  9. "&Open...", self, shortcut=QKeySequence.Open,
  10. triggered=self.open)
  11. fileMenu.addAction(openAction)
  12. exitAction = QAction(QIcon.fromTheme("application-exit"), "E&xit",
  13. self, shortcut="Ctrl+Q", triggered=self.close)
  14. fileMenu.addAction(exitAction)
  15. playMenu = self.menuBar().addMenu("&Play")
  16. playIcon = QIcon(QPixmap(":/icons/play.png"))
  17. self.playAction = toolBar.addAction(playIcon, "Play")
  18. self.playAction.triggered.connect(self.player.play)
  19. playMenu.addAction(self.playAction)
  20. previousIcon = QIcon(QPixmap(":/icons/previous.png"))
  21. self.previousAction = toolBar.addAction(previousIcon, "Previous")
  22. self.previousAction.triggered.connect(self.previousClicked)
  23. playMenu.addAction(self.previousAction)
  24. pauseIcon = QIcon(QPixmap(":/icons/pause.png"))
  25. self.pauseAction = toolBar.addAction(pauseIcon, "Pause")
  26. self.pauseAction.triggered.connect(self.player.pause)
  27. playMenu.addAction(self.pauseAction)
  28. nextIcon = QIcon(QPixmap(":/icons/forward.png"))
  29. self.nextAction = toolBar.addAction(nextIcon, "Next")
  30. self.nextAction.triggered.connect(self.playlist.next)
  31. playMenu.addAction(self.nextAction)
  32. stopIcon = QIcon(QPixmap(":/icons/stop.png"))
  33. self.stopAction = toolBar.addAction(stopIcon, "Stop")
  34. self.stopAction.triggered.connect(self.player.stop)
  35. playMenu.addAction(self.stopAction)
  36. # many lines were omitted

执行 python main.py 来运行应用程序,检查新的图标集

为 控件 应用程序 设置 样式

https://doc.qt.io/qtforpython/tutorials/basictutorial/widgetstyling.html

Qt Widgets 应用程序根据平台使用默认主题。在某些情况下需要修改 Qt 主题的配置让应用程序以不同的方式显示。可以位控件提供自定义样式。

  1. # -*- coding: utf-8 -*-
  2. import sys
  3. from PySide6.QtCore import Qt
  4. from PySide6.QtWidgets import QApplication, QLabel
  5. if __name__ == "__main__":
  6. app = QApplication()
  7. w = QLabel("This is a placeholder text")
  8. w.setAlignment(Qt.AlignCenter)
  9. w.resize(300, 150)
  10. w.show()
  11. sys.exit(app.exec())

可以使用类似 CSS 的语法为 应用程序设置样式。有关详细信息,请参阅 Qt 样式表参考:Qt Style Sheets Reference | Qt Widgets 5.15.16

QLabel 可以通过设置它的一些 CSS 属性来设置不同的样式,例如:background-color 和 font-family,示例:

  1. # -*- coding: utf-8 -*-
  2. import sys
  3. from PySide6.QtCore import Qt
  4. from PySide6.QtWidgets import QApplication, QLabel
  5. if __name__ == "__main__":
  6. app = QApplication()
  7. w = QLabel("This is a placeholder text")
  8. w.setAlignment(Qt.AlignCenter)
  9. w.setStyleSheet("""
  10. background-color: #262626;
  11. color: #FFFFFF;
  12. font-family: Titillium;
  13. font-size: 18px;
  14. """)
  15. w.resize(300, 150)
  16. w.show()
  17. sys.exit(app.exec())

上面代码中单独设置每个 UI 元素的样式需要做很多工作。更简单的替代方法是使用 Qt 样式表,它是一个或多个 .qss 文件,用于定义应用程序中 UI 元素的样式。

更多示例可以在 (  Qt 样式表示例: Qt Style Sheets Examples | Qt Widgets 5.15.16 ) 文档页面中找到。

Qt 样式表

qss文件与 CSS 文件非常相似,但您需要指定 Widget 组件以及可选的对象名称:

  1. QLabel {
  2. background-color: red;
  3. }
  4. QLabel#title {
  5. font-size: 20px;
  6. }

第一个样式为应用程序中的所有 QLabel 对象定义背景颜色,而后一个样式仅设置标题对象的样式。程序中可以通过 setObjectName(str) 函数,为任何 Qt 对象设置对象名称,例如:对于 label = QLabel("Test") ,设置 label.setObjectName("title")。

一旦你的应用程序有了一个qss文件,你可以通过读取文件并使用 QApplication.setStyleSheet(str)函数来应用它:

  1. if __name__ == "__main__":
  2. app = QApplication()
  3. w = Widget()
  4. w.show()
  5. with open("style.qss", "r") as f:
  6. _style = f.read()
  7. app.setStyleSheet(_style)
  8. sys.exit(app.exec())

通过 qss,可以让 程序代码 和 样式 分开设计,这样的设计不会导致 代码和样式混淆到一块,也可以很方便的 启用或禁用 样式。

示例:

  1. # -*- coding: utf-8 -*-
  2. import sys
  3. from PySide6.QtCore import Qt
  4. from PySide6.QtWidgets import *
  5. _style = """
  6. QListWidget {
  7. color: #FFFFFF;
  8. background-color: #33373B;
  9. }
  10. QListWidget::item {
  11. height: 50px;
  12. }
  13. QListWidget::item:selected {
  14. background-color: #2ABf9E;
  15. }
  16. QLabel {
  17. background-color: #FFFFFF;
  18. qproperty-alignment: AlignCenter;
  19. }
  20. QPushButton {
  21. background-color: #2ABf9E;
  22. padding: 20px;
  23. font-size: 18px;
  24. }
  25. """
  26. class Widget(QWidget):
  27. def __init__(self, parent=None):
  28. super(Widget, self).__init__(parent)
  29. menu_widget = QListWidget()
  30. for i in range(10):
  31. item = QListWidgetItem(f"Item {i}")
  32. item.setTextAlignment(Qt.AlignCenter)
  33. menu_widget.addItem(item)
  34. text_widget = QLabel("标签")
  35. button = QPushButton("按钮")
  36. content_layout = QVBoxLayout()
  37. content_layout.addWidget(text_widget)
  38. content_layout.addWidget(button)
  39. main_widget = QWidget()
  40. main_widget.setLayout(content_layout)
  41. layout = QHBoxLayout()
  42. layout.addWidget(menu_widget, 1)
  43. layout.addWidget(main_widget, 4)
  44. self.setLayout(layout)
  45. if __name__ == "__main__":
  46. app = QApplication()
  47. w = Widget()
  48. w.show()
  49. # with open("style.qss", "r") as f:
  50. # _style = f.read()
  51. # app.setStyleSheet(_style)
  52. app.setStyleSheet(_style)
  53. sys.exit(app.exec())

2、Quick/QML:基础教程

第一个 QtQuick/QML 应用程序

QML 是一种声明性语言,可让您比使用传统语言更快地开发应用程序。由于其声明性,它非常适合设计应用程序的 UI。在 QML 中,用户界面被指定为具有属性的对象树。在本教程中,我们将展示如何使用 PySide6 和 QML 制作一个简单的“Hello World”应用程序。

PySide6/QML 应用程序至少包含两个不同的文件——一个包含用户界面 QML 描述的文件,以及一个加载 QML 文件的 python 文件。为了方便起见,让我们将这两个文件保存在同一个目录中。

这是一个简单的 QML 文件,名为view.qml

  1. import QtQuick
  2. Rectangle {
  3. id: main
  4. width: 200
  5. height: 200
  6. color: "green"
  7. Text {
  8. text: "Hello World"
  9. anchors.centerIn: main
  10. }
  11. }

我们首先导入QtQuick,这是一个 QML 模块。

对于以前使用过 HTML 或 XML 文件的人来说,其余的 QML 代码非常简单。基本上,我们正在创建一个大小为200*200的绿色矩形,并添加一个文本元素,内容为“Hello World”。该代码使文本在对象中居中显示,在本例中为 Rectangle。anchors.centerIn: mainid: main

现在,让我们看看代码在 PySide6 上的样子。让我们称之为main.py

  1. import sys
  2. from PySide6.QtWidgets import QApplication
  3. from PySide6.QtQuick import QQuickView
  4. if __name__ == "__main__":
  5. app = QApplication()
  6. view = QQuickView()
  7. view.setSource("view.qml")
  8. view.show()
  9. sys.exit(app.exec())

Python-QML 集成

Python-QML integration - Qt for Python

QML 应用教程

QML Application Tutorial - Qt for Python

QML、SQL 和 PySide 集成教程

QML, SQL and PySide Integration Tutorial - Qt for Python

3、一般应用

数据可视化工具教程

Data Visualization Tool Tutorial - Qt for Python

学习如何在折线图中可视化来自 CSV 的数据。

您可以从 下载源代码 https://doc.qt.io/qtforpython/_downloads/06ada84b04e72c9468651471cc91b026/datavisualize.tar.bz2 。

综合教程

Expenses Tool Tutorial - Qt for Python

学习以下概念:

  • 以编程方式创建用户界面

  • 布局、控件

  • 重载 Qt 类

  • 连接信号和插槽

  • 与 QWidgets 交互

要求:

  • 应用程序的简单窗口(QMainWindow)。

  • 用于跟踪费用的表(QTableWidget)。

  • 添加费用信息的两个输入字段(QLineEdit)。

  • 用于向表格添加信息、绘制数据、清除表格和退出应用程序的按钮 ( QPushButton )。

  • 避免无效数据输入的验证步骤。

  • 用于可视化将嵌入图表视图 ( QChartView )的费用数据 ( QChart ) 的图表。

  1. # -*- coding: utf-8 -*-
  2. import sys
  3. from PySide6.QtCore import Qt, Slot
  4. from PySide6.QtGui import QAction, QPainter
  5. from PySide6.QtWidgets import (
  6. QApplication, QHeaderView, QHBoxLayout, QLabel, QLineEdit,
  7. QMainWindow, QPushButton, QTableWidget, QTableWidgetItem,
  8. QVBoxLayout, QWidget
  9. )
  10. from PySide6.QtCharts import QChartView, QPieSeries, QChart
  11. class Widget(QWidget):
  12. def __init__(self):
  13. QWidget.__init__(self)
  14. self.items = 0
  15. # Example data
  16. self._data = {
  17. "Water": 24.5, "Electricity": 55.1, "Rent": 850.0,
  18. "Supermarket": 230.4, "Internet": 29.99, "Bars": 21.85,
  19. "Public transportation": 60.0, "Coffee": 22.45, "Restaurants": 120
  20. }
  21. # Left
  22. self.table = QTableWidget()
  23. self.table.setColumnCount(2)
  24. self.table.setHorizontalHeaderLabels(["Description", "Price"])
  25. self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
  26. # Chart
  27. self.chart_view = QChartView()
  28. self.chart_view.setRenderHint(QPainter.Antialiasing)
  29. # Right
  30. self.description = QLineEdit()
  31. self.price = QLineEdit()
  32. self.add = QPushButton("Add")
  33. self.clear = QPushButton("Clear")
  34. self.quit = QPushButton("Quit")
  35. self.plot = QPushButton("Plot")
  36. # Disabling 'Add' button
  37. self.add.setEnabled(False)
  38. self.right = QVBoxLayout()
  39. self.right.addWidget(QLabel("Description"))
  40. self.right.addWidget(self.description)
  41. self.right.addWidget(QLabel("Price"))
  42. self.right.addWidget(self.price)
  43. self.right.addWidget(self.add)
  44. self.right.addWidget(self.plot)
  45. self.right.addWidget(self.chart_view)
  46. self.right.addWidget(self.clear)
  47. self.right.addWidget(self.quit)
  48. # QWidget Layout
  49. self.layout = QHBoxLayout()
  50. # self.table_view.setSizePolicy(size)
  51. self.layout.addWidget(self.table)
  52. self.layout.addLayout(self.right)
  53. # Set the layout to the QWidget
  54. self.setLayout(self.layout)
  55. # Signals and Slots
  56. self.add.clicked.connect(self.add_element)
  57. self.quit.clicked.connect(self.quit_application)
  58. self.plot.clicked.connect(self.plot_data)
  59. self.clear.clicked.connect(self.clear_table)
  60. self.description.textChanged[str].connect(self.check_disable)
  61. self.price.textChanged[str].connect(self.check_disable)
  62. # Fill example data
  63. self.fill_table()
  64. @Slot()
  65. def add_element(self):
  66. des = self.description.text()
  67. price = self.price.text()
  68. try:
  69. price_item = QTableWidgetItem(f"{float(price):.2f}")
  70. price_item.setTextAlignment(Qt.AlignRight)
  71. self.table.insertRow(self.items)
  72. description_item = QTableWidgetItem(des)
  73. self.table.setItem(self.items, 0, description_item)
  74. self.table.setItem(self.items, 1, price_item)
  75. self.description.setText("")
  76. self.price.setText("")
  77. self.items += 1
  78. except ValueError:
  79. print("Wrong price", price)
  80. @Slot()
  81. def check_disable(self, s):
  82. if not self.description.text() or not self.price.text():
  83. self.add.setEnabled(False)
  84. else:
  85. self.add.setEnabled(True)
  86. @Slot()
  87. def plot_data(self):
  88. # Get table information
  89. series = QPieSeries()
  90. for i in range(self.table.rowCount()):
  91. text = self.table.item(i, 0).text()
  92. number = float(self.table.item(i, 1).text())
  93. series.append(text, number)
  94. chart = QChart()
  95. chart.addSeries(series)
  96. chart.legend().setAlignment(Qt.AlignLeft)
  97. self.chart_view.setChart(chart)
  98. @Slot()
  99. def quit_application(self):
  100. QApplication.quit()
  101. def fill_table(self, data=None):
  102. data = self._data if not data else data
  103. for desc, price in data.items():
  104. description_item = QTableWidgetItem(desc)
  105. price_item = QTableWidgetItem(f"{price:.2f}")
  106. price_item.setTextAlignment(Qt.AlignRight)
  107. self.table.insertRow(self.items)
  108. self.table.setItem(self.items, 0, description_item)
  109. self.table.setItem(self.items, 1, price_item)
  110. self.items += 1
  111. @Slot()
  112. def clear_table(self):
  113. self.table.setRowCount(0)
  114. self.items = 0
  115. class MainWindow(QMainWindow):
  116. def __init__(self, widget):
  117. QMainWindow.__init__(self)
  118. self.setWindowTitle("Tutorial")
  119. # Menu
  120. self.menu = self.menuBar()
  121. self.file_menu = self.menu.addMenu("File")
  122. # Exit QAction
  123. exit_action = QAction("Exit", self)
  124. exit_action.setShortcut("Ctrl+Q")
  125. exit_action.triggered.connect(self.exit_app)
  126. self.file_menu.addAction(exit_action)
  127. self.setCentralWidget(widget)
  128. @Slot()
  129. def exit_app(self, checked):
  130. QApplication.quit()
  131. if __name__ == "__main__":
  132. # Qt Application
  133. app = QApplication(sys.argv)
  134. # 创建 my_widget
  135. my_widget = Widget()
  136. # QMainWindow using QWidget as central widget
  137. window = MainWindow(my_widget)
  138. window.resize(800, 600)
  139. window.show()
  140. # Execute application
  141. sys.exit(app.exec())

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小惠珠哦/article/detail/962991
推荐阅读
相关标签
  

闽ICP备14008679号