PyQt5提供了一个可视化图形工具Qt Designer,文件名为designer.exe。如果在电脑上找不到,可以用如下命令进行安装:

  1. pip install PyQt5-tools

安装完毕后,可在如下目录找到此工具软件:
%LOCALAPPDATA%\Programs\Python\Python39\Lib\site-packages\qt5_applications\Qt\bin\designer.exe

注意:%LOCALAPPDATA%通常代表C:\Users\你的用户名\AppData\Local\

VSCode添加外部工具

QtDesigner

打开PYQT Integration插件设置,搜索designer,将自己本地的designer.exe完整路径设置进去。
image.png :::warning 注意,如果找不到designer.exe

  1. Program路径要根据自己安装的PyQt5-tools路径设置(pip install PyQt5-tools
  2. 安装的PyQt5-tools路径的取决于安装Python时的路径(pip -V可以看到路径)
  3. 如果用的是Python3.9.x,尝试用以下路径文件(先尝试在Win+R中能否打开):

%LOCALAPPDATA%\Programs\Python\Python39\Lib\site-packages\qt5_applications\Qt\bin\designer.exe

  1. 实在找不到,建议安装everything.exe,全局搜索designer.exe位置 ::: 设置完成后,我们可以在.ui文件右键进行如下操作:
    image.png
    也可以在任意目录右键新建ui文件

    PyUIC

    打开设置,过滤pyuic,按照下图填写:
  • Cmd:pyuic5
  • Add Options:--import-from=ui
  • Filepath:Ui_${ui_name}.py

image.png
这个配置是为了右键.ui文件时,点击PYQT:Compile Form时,能生成对应.py文件

PyRCC

确保配置如下即可:
image.png
添加完成后,可在.qrc文件右键点击PYQT: Compile Resource,即可生成对应的.py资源文件。
image.png

加载UI文件模板代码

QMainWindow

我们通过可视化工具QtDesigner生成.ui文件后,需要在代码中加载并显示。可参照PyUIC部分教程进行转换。

使用xxx.ui生成xxx.py代码文件后,可使用如下代码进行加载。
注意,本例的ui相关文件都在ui目录下,即加载的ui包下的ui_main_window模块

  1. """
  2. PyQt5版GUI工具
  3. """
  4. from PyQt5.QtWidgets import *
  5. from PyQt5.QtCore import *
  6. from PyQt5.QtGui import *
  7. from ui.Ui_main_window import Ui_MainWindow
  8. import sys
  9. class MainWindow(QMainWindow):
  10. def __init__(self):
  11. super().__init__()
  12. # 创建对象
  13. self.ui = Ui_MainWindow()
  14. # 初始化内容
  15. self.ui.setupUi(self)
  16. # 初始化ui
  17. self.init_ui()
  18. def init_ui(self):
  19. pass
  20. def main():
  21. app = QApplication(sys.argv)
  22. window = MainWindow()
  23. window.show()
  24. sys.exit(app.exec_())
  25. if __name__ == '__main__':
  26. main()

目录结构如下
image.png

QWidget

  1. from PyQt5.QtWidgets import *
  2. from PyQt5.QtCore import *
  3. from PyQt5.QtGui import *
  4. import sys
  5. # 帮我们直接运行此文件时,可以加载到上级目录的ui包
  6. sys.path.append("../")
  7. from ui.Ui_my_widget import Ui_MyWidget
  8. class MyWidget(QWidget):
  9. def __init__(self, parent=None):
  10. super().__init__(parent)
  11. self.ui = Ui_MyWidget()
  12. self.ui.setupUi(self)
  13. self.init_ui()
  14. def init_ui(self):
  15. pass
  16. if __name__ == '__main__':
  17. app = QApplication(sys.argv)
  18. window = MyWidget()
  19. window.show()
  20. sys.exit(app.exec_())

QDialog

  1. from PyQt5.QtWidgets import *
  2. from PyQt5.QtCore import *
  3. from PyQt5.QtGui import *
  4. from ui.Ui_serial_setting_dialog import Ui_SerialSettingDialog
  5. import sys
  6. class SerialSettingDialog(QDialog):
  7. def __init__(self, parent=None):
  8. super().__init__(parent)
  9. self.ui = Ui_SerialSettingDialog()
  10. self.ui.setupUi(self)
  11. # 可以通过此设置,固定对话框的大小
  12. self.setFixedSize(self.width(), self.height())
  13. self.initUi()
  14. self.baudrate = None
  15. def initUi(self):
  16. pass
  17. def accept(self):
  18. super().accept()
  19. print("accept")
  20. # 读取当前波特率的设置值
  21. self.baudrate = self.ui.cb_bt.currentText()
  22. def reject(self):
  23. super().reject()
  24. print("reject")
  25. if __name__ == '__main__':
  26. app = QApplication(sys.argv)
  27. dialog = SerialSettingDialog()
  28. dialog.show()
  29. sys.exit(app.exec_())

常用知识点

修改标题图标

图片资源管理

图片按钮

  1. background-color: transparent;
  2. border: none;

加载对话框

动态加载Widget

修改主题

qt-material
主题官网:https://github.com/UN-GCPDS/qt-material
使用方式:
安装:

  1. pip install qt-material

代码:

  1. from qt_material import apply_stylesheet
  2. app = QtWidgets.QApplication(sys.argv)
  3. window = QtWidgets.QMainWindow()
  4. # setup stylesheet
  5. apply_stylesheet(app, theme='dark_teal.xml')
  6. # run
  7. window.show()
  8. app.exec_()

效果:
Qt Designer - 图7

其他注意事项

事件被多次触发

问题描述:
如果自己给某个按钮或组件的信号设置槽函数,期待点击一次只触发一次,但是莫名被触发了多次。

原因分析:
参考文档介绍:QMetaObject - Qt for Python

原因很可能是因为槽函数命名问题。因为我们使用.ui文件生成的.py文件中,会执行一个如下的方法。帮我们根据组件的变量名绑定对应的槽函数:

  1. QtCore.QMetaObject.connectSlotsByName(ChatRoomsWidget)

假设我们的对象有一个QPushButton类型的子对象,对象名称为button1。则自动connect且捕获按钮的clicked()信号的槽是:

  1. def on_button1_clicked():

如果对象本身有一个通过[setObjectName()](https://doc.qt.io/qtforpython-6/PySide6/QtCore/QObject.html#PySide6.QtCore.PySide6.QtCore.QObject.setObjectName)设置的对象名称,它自己的信号也连接到它对应的槽。

解决办法:
换一个槽函数名称,或是按照官方规则直接声明槽函数