Qt Notes
文章目录
教程
PySide6 官方:Qt for Python — Qt for Python
- Tutorials 基础教程: Qt for Python Tutorials — Qt for Python
Qt 各个模块简介
相关类查询帮助
google 搜索 <类名> + PySide6 –> 右相关官方文档
- 例如:QObject — Qt for Python 即为 PySide6 对 QObject 的解说
zetcode Qt 教程
PyQt5
- 系列博客 csdn: PyQt5快速开发与实战-学习笔记_jia666666 的博客-CSDN博客
中文教程
- 博主专业路过:qt5 总结
- 博主水之心:Qt for Python - 连载 - 简书
- 系列博客:《Qt 实战一二三》_青春不老,奋斗不止!-CSDN博客
- 写了超多 Qt 博客: Shijia Yin_CSDN 博客-Qt基础,python,C++领域博主
Qt Python 教程
PyQt5 Tutorial 2022, Create Python GUIs with Qt
- 各种 PyQt, PySide, matplotlib 在 Qt 中实用等等
书籍
概念
基本概念
Model/View
主要类
Model
- 抽象基类 QAbstractItemModel
实现类
- QFileSystemModel
QStringListModel
- string list 字符串列表
View
- 抽象基类 QAbstractItemView
实现类
QTableView
- 即表格,类似 Excel
- QListView
QHeaderView
- table 和 tree 都有表头
Delegate
- 抽象基类 QAbstractItemDelegate
实现类
QStyledItemDelegate
- 简单工具可以继承它,而不是 QAbstractItemDelegate
分工
标准 MVC 框架
- Model : 负责数据
- View : 负责展示
- Controller : 负责交互,用户的操作
Qt Model/View
- 参考:Model/View Programming | Qt Widgets 5.15.5
- Model : 负责数据
- View : 负责展示和交互
- delegate: 负责用户输入获取,和获取的结果展示
Model
- 负责数据访问
View
- 整体布局 Layout
- 在需要处理和编辑时,与 Delegate 合作 Editing
- 展示 Present
- 跳转 Navigation
- 选择 Selection
交互
- 拖拽 Drag and Drop
- 右键菜单 Context Menu
- 编辑工具
访问
QModelIndex
- 通过 (row, column, parent_index) 获取
- 父 Item –> parent_index
Role 角色
- Qt::ItemDataRole (枚举类型)
作用:同一个 item 可以存储不同类型数据
- 类似 一个 python dict {key: vlaue, …}
- 为不同用途,提供不同数据
获取
model->data(index, role_type)
使用简介
使用 Model Index
使用 Model
使用 View
多个 View 共用 同一个 Model
- 参考:Model/View Programming | Qt Widgets 5.15.5
- 选择:各个 view 可以有自己的选择 selection
- 数据:共享数据,因为是同一个 model
选择的处理
- 参考:Model/View Programming | Qt Widgets 5.15.5
实现类
QItemSelectionModel- 获取
your_view.selectionModel() - 设置
your_view.setSelectionModel()
- 获取
共享选择实现
两个 View 使用同一个 SelectionModel
1secondTableView->setSelectionModel(firstTableView->selectionModel());
使用 Delegate
- 参考:Model/View Programming | Qt Widgets 5.15.5
- 默认实现类:QStyledItemDelegate
获取和设置
your_view.itemDelegate()your_view.setItemDelegate()
窗口部件
QDialog
QColorDialog –> class + head file
method
| |
–> constructor QDialog(Qt::red, this)
–> method setOption(QColorDialog::ShowAlphaChannel) exec() —>以模态方式运行 currentColor() —> 返回 QColor
QFileDialog
methods
- QFileDialog::getOpenFileName(this, Title, "d:"
默认路径, ("图片文件(*png *jpg);; (文本文件(*txt))"))
- QFileDialog::getOpenFileName(this, Title, "d:"
Qt Creator 软件操作
帮助
- 定位到帮助模式: Ctrl + 6
- 添加书签:Ctrl + M
索引搜索:Alt + L 进入搜索框
- 进入索引模式:Alt + i (似乎不正确)
Qt 工具
Qt Assistant
- 用于帮助文档
Qt Designer
Qt Linguist
快速查找文件
- 快捷键: Ctrl + K
查找方式:可以使用通配符*
- 如:he*ui –> helloworld.ui
代码自动补全
- 强制补全:Ctrl + <SPACE>
发布软件
文件复制
创建软件的文件夹
- 新建一个文件夹,重命名为“我的第一个 Qt 程序”,
复制应用程序
- 然后将 release 文件夹中的 helloworld.exe 复制过来,
复制动态链接库文件,即: .dll 文件
再去 Qt 安装目录的 bin 目录中将
libgcc_s_dw2-1.dll、 libstdc++-6.dll、 libwinpthread-1.dll、 Qt5Core.dll、Qt5Gui.dll 和 Qt5Widgets.dll 这 6 个文件复制过来 ,。
复制模块插件所需要的 dll 动态库文件
- 另外,还需要将 C:\Qt\Qt5.6.1\5.6mingw49_32\plugins 目录中的 platforms 文件夹复制过来 (不要修改该文件夹名称),里面只需要保留 qwindows.dll 文件即可
发布软件需要的的文件列表
– libgcc_s_dw2-1.dll – libstdc++-6.dll – libwinpthread-1.dll helloworld –|– Qt5Core.dll
– Qt5Gui.dll – Qt5Widgets.dll – plateforms – qwindows.dll – helloworld.exe 软件编写中用到特别的模块,要适当添加文件
图片
- 若程序中使用了 png 以外格式的图片, 在发布程序时就要将 Qt 安装目录下的 plugins 目录 中的 imageformats 文件夹复制到发布程序文件夹中, 其中只要保留自己用到的文件格式的 dll 文件即可。
- 例如:用到了 gif 文件,那么只需要保留 qgif.dll。
数据库
- 而如果程序中使用了其他的模块,比如数据库, 那么就要将 plugins 目录中的 sqldrivers 文件夹复制过来, 里面保留自己用到的数据库驱动。
设置应用程序图标
图标图片命名
- myico.ico
- 复制到 source file 源文件目录
在 helloworld.pro 文件中添加
- RC_ICONS = myico.ico
- 重新编译运行程序
创建 Qt 程序
纯代码编写 Qt 程序
使用 Qt Creator
选择模板时
- 选 empty qmake project
修改 project 文件
- 在 helloworld.pro 添加下述代码
- greaterThan(QT_MAJOR_VERSION, 4): QT += widigets
- 添加 main.cpp 的源代码
- 编译运行
使用命令行 terminal
- 添加 main.cpp 等源代码
使用开始菜单中的 MinGW(Qt 5.6 for Desktop (MinGW 4.9.2 32 bit))
- cd HelloWorld 程序文件夹
这个 MinGW for Desktop 的目录
- 默认路径在 C:\Qt\Qt5.6.1\5.6mingw49_32
- 在 bin 下有 qtenv2.bat
生成 project 文件.pro
- qmake -project
修改 project 文件
- 在 helloworld.pro 添加下述代码
- greaterThan(QT_MAJOR_VERSION, 4): QT += widigets
直接使用 qmake 命令生成 Makefile
- qmake
使用 mingw32-make 命令编译
- mingw32-make
运行程序
1 2 3 4 5 6 7$qmake –project $vim *.pro 这时在helloworld.pro文件中添加QT += widgets ,然后依次执行如下命令: $qmake $mingw32-make $cd release $./helloworld.exe
使用.ui 文件
在 Qt Creator 中使用.ui 文件
添加.ui 文件
- hellodialog.ui
- add file 添加文件
选择模板
- Dialog without buttons
- 在 Qt Designer 中编辑,保存
build,生成对应的头文件
- build 生成:Ctrl + Shift + B
- ui_helloworld.h
在 main.cpp 中添加内容
- 操纵 hellodialog.ui
- Ui::HelloDialog ui;
ui.setupUi(&window);
1 2 3 4 5 6 7 8 9 10#include "ui_hellodialog.h" // <---*** this was added int main(int argc, char *argv[]) { QApplication a(argc, argv); QDialog w; Ui::HelloDialog ui; // <---*** this was added ui.setupUi(&w); // <---*** this was added w.show(); return a.exec(); }
- 编译运行
注: build 即生成,包括编译连接两步。
在命令行 terminal 中使用.ui 文件
复制.ui 文件与 main.cpp 等源代码
- hellodialog.ui
- .ui 需要在 Qt Creator 中先创建
编译.ui 文件
- uic hellodialog.ui -o ui_hellodialog.h
创建项目其余部分
如上面从 terminal 创建 Qt 一样
1 2 3 4 5 6 7$qmake –project $vim *.pro 这时在helloworld_2.pro文件中添加QT += widgets ,然后依次执行如下命令: $qmake $mingw32-make $cd release $./helloworld.exe
自定义 C++类
创建空项目
- Empty qmake project
- .pro 文件添加:greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
创建自定义 C++类
- 添加文件
选择 C++类,
- 基类选择自定义<Custom>
- 再选择或填写 QDialog
- 类名:HelloDialog
添加 main.cpp 源代码
1 2 3 4 5 6 7 8 9#include <QApplication> #include "hellodialog.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); HelloDialog w; w.show(); return a.exec(); }- 添加.ui 文件 helloworld.ui
更改 C++类,HelloDialog
- 不在使用 main.cpp 操纵.ui 文件
- 在 HelloDialog 类中操纵.ui 文件
如何操纵:
eg:
1 2Ui::Hellodialog *ui; ui->setupUi();- 在新 C++类中包含一个 Ui::HelloDialog 对象
C++类源码:
头文件
eg: hellodialog.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21#ifndef HELLODIALOG_H #define HELLODIALOG_H #include<QDialog> namespace Ui { class HelloDialog; } class HelloDialog: public QDialog { Q_Object public: explicit HelloDialog(QWidget* parent=0); ~HelloDialog(); private: Ui::HelloDialog *ui; } #endif
新 C++类,实现文件 cpp
hellodialog.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17#include "hellodialog.h" #include "ui_hellodialog.h" HelloDialog::HelloDialog(QWidget *parent) : QDialog(parent) { ui = new Ui::HelloDialog; ui->setupUi(this); } /* ,* 或者这样 HelloDialog::HelloDialog(QWidget *parent) : QDialog(parent), ui(new Ui::HelloDialog) { ui->setupUi(this); } ,*/
- 编译运行
使用 Qt designer,Qt 设计师界面类
创建空项目
- Empty qmake project
- .pro 文件添加:greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
添加文件
模板选择
- Qt 设计师界面类,Qt designer form class
- Dialog without buttons
- 这样会同时添加一个 head file 头文件和一个 form 即.ui 文件
- 相当于上面的自定义一个 C++类,再添加一个.ui 文件
修改 main.cpp
1 2 3 4 5 6 7 8 9#include <QApplication> #include "hellodialog.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); HelloDialog w; w.show(); return a.exec(); }
关于.ui 文件与头文件
文件列表
- hellodialog.ui
ui_hellodialog.h
class Ui_HelloDialog
- 没有继承其他类
namespace Ui{ class HelloDialog: public Ui_HelloDialog; }
1 2 3 4 5 6 7 8 9 10 11 12QT_BEGIN_NAMESPACE // begin class Ui_HelloDialog { }; //有分号 namespace Ui { class HelloDialog: public Ui_HelloDialog; //继承.ui文件中的自动生成类 } //没分号 QT_END_NAMESPACE //end **-->注意这一对宏
hellodialog.h
- class HelloDialog: public QDialog{};
- namespace Ui{class HelloDialog;}
- 不包含#include"ui_hellodialog.h"
hellodialog.cpp
- #include"ui_hellodialog.h"
- #include"hellodialog.h"
注意:
对应的 form 文件.ui,类文件
- 使用相同的名字 hellodialog
对应的类
- 使用相同的名字 HelloDialog, Ui_HelloDialog
类 HelloDialog 包含一个通类型的指针
- Ui::HelloDialog* ui = new Ui::HelloDialog
初始化方法
放到构造函数的函数体中
1 2 3 4 5 6HelloDialog::HelloDialog(QWidget *parent) : QDialog(parent), { ui= new Ui::HelloDialog; ui->setupUi(); };或者放到构造函数的初始化列表中
1 2 3 4 5 6HelloDialog::HelloDialog(QWidget *parent) : QDialog(parent), ui(new Ui::HelloDialog) { ui->setupUi(); };
字符串
实现多语言
- 使用 string = QObject::tr("your string text")
Qt 类的定义
在类定义的第一行添加 Q_Object
- Q_Object
- 扩展 c++类的功能
必须在最开始添加
1 2 3 4 5 6 7 8 9class HelloDialog: public QDialog { Q_Object // 最开始添加,没有分号 public: int i; // ... }
show()显示函数,调用 message loop
- 有几个 show()就有几个窗口 window
QWidget
- 最基础的 Qt 用户界面类的基类
- 被称为基础窗口部件类,基础 widget
父类:
- QObject
- QPaintDevice
窗口部件 Widget,简称部件
- 大窗口的组成元素,
- 如:按钮,标签 Label,对话框等等
窗口状态 WindowStates
flags, 目的:
用来标记窗口状态
- 最小化:Qt::WindowMinimized
- 最大化:Qt::WindowMaximized
- 全屏:Qt::WindowFullScreen
- 激活状态,键盘作用的地方: Qt::WindowActive
- 正常状态:Qt::WindowNoState
设置方法:
- widget->setWindowState(Qt::WindowStates state)
Qt 枚举型
特征:
如:Qt::WindowNoState,Qt::WindowStates 类型
- 以 Qt 开头
- 每个单词首字母都大写
如:Qt::GlobalColor 类型,Qt::white
- 枚举元素,也可能全小写字母
如:Qt::AA_DontShowIconsInMenus,Qt::ApplicationAtribute 类型
- 加类型前缀大写字母
如:Qt::Key_Tab,Qt::Key 类型
- 加类型名当前缀
窗口
定义:
- 没有父部件的部件
独特性质:
- 没有 parent 父部件
一般性质:
有边框
无边框方法:
- Qt::WindowFlags f=…
- 有标题栏
名词:
- 顶级部件 top-level widget: 即窗口
- 子部件 child-level widget
构造函数
QWidget(QWidget* parent=nullprt, Qt::WindowFlags f=…)
1QWidget *widget = new QWidget(0, Qt::Dialog | Qt::FramelessWindowHint);
Qt::WindowFlags
- 枚举类型 enum
成员:
- Qt::FramelessWindowHint 无边框
- Qt::SplashScreen
- Qt::WindowStaysOnTopHint 停留在其他窗口上面
几何布局
两个特殊的点(位置)
pos(): 窗口的最左上角
坐标:
- pos().x()
- pos().y()
geometry(): 窗口主内容部分的最左上角,返回 QRect
坐标:
- geometry.x()
- geometry.y()
另一层意思:内容部分尺寸
- 宽:geometry.width()同 width()
- 高: geometry.height()同 height()
主窗口部分
- frameGeometry()返回 QRect
- 宽:frameGeometry().width()
- 高:frameGeometry().height()
主内容部分
- 宽:geometry.width()同 width()
- 高: geometry.height()同 height()
移动:
- move():作用的是主窗口的 pos(),x,y
几个位置函数
- rect()不包含 frame
- size()不包含 frame
- 包含框架:x()、y()、frameGeometry()、pos()和 move()等函数;
- 不包含框架:geometry()、width()、height()、rect()和 size()等函数。
QDialog
模态
模态对话框
- 模态 Modal
特点:
- 不关闭该窗口,不能操作其他窗口
实现方法
调用对应的 app.exec()
1 2QDialog dialog(this); dialog.exec();show()之前调用 setModal()
1 2 3QDialog *dialog = new QDialog(this); dialog->setModal(true); dialog->show();使用 setWindowModality()
方法来源:
- 继承自 QWidget
输入参数
- Qt::NonModal(不阻塞任何窗口,就是非模态)
- Qt::WindowModal(阻塞它的父窗口和所有祖先窗口以及它们的子窗口)
- Qt::ApplicationModal(阻塞整个应用程序的所有窗口)
- setModal()函数默认设置的是 Qt::ApplicationModal
信号处理
信号发出者
- QDialog::accept(), QDialog::reject()
信号传递者
QDialog::exec()
返回类型
QDialog::QDialogCode 枚举型
成员:
- QDialog::Accepted
- QDialog::Rejected
运作方式
QDialog::accept() <—> 发出 QDialog::Accepted
Hides the modal dialog and sets the result code to Accepted
- 隐藏模态 Qdialog,返回信号 QDialog::Accepted
- 在模态的 dialog 中的槽中调用 accept(),
- dialog->exec()返回 QDialog::Accepted
QDialog::reject() <—> 发出 QDialog::Rejected
- 在模态的 dialog 中的槽中调用 reject()
- dialog->exec()返回 QDialog::Rejected
非模态对话框
特点:
- 开着它,也能操作别的窗口
实现方法
使用 show()函数来显示
1 2QDialog *dialog = new QDialog(this); dialog->show();
标准对话框
颜色对话框 QColorDialog
使用方式
- 静态方法
- 直接创建实例
接口
1 2 3 4 5 6 7 8 9 10getColor(default_color, parent, window_title, dialog_options) // QColor color = QColorDialog::getColor(Qt::red, this, tr("颜色对话框"), // QColorDialog::ShowAlphaChannel); QColorDialog dialog(Qt::red, this); // 创建对象 dialog.setOption(QColorDialog::ShowAlphaChannel); // 显示alpha选项 dialog.exec(); // 以模态方式运行对话框 QColor color = dialog.currentColor(); // 获取当前颜色 qDebug() << "color: " << color;
文件对话框 QFileDialog
接口
1 2 3 4 5 6 7 8 9QString str= QFileDialog::getOpenFileName(parent,titleStr,str_directory,tr("Image (*.png *.jpg)")); // QString fileName = QFileDialog::getOpenFileName(this, tr("文件对话框"), // "D:", tr("图片文件(*png *jpg);;文本文件(*txt)")); // qDebug() << "fileName:" << fileName; QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("文件对话框"), "D:", tr("图片文件(*png *jpg)")); qDebug()<< "fileNames:" << fileNames;
字体对话框 QFontDialog
1 2 3 4 5 6 7 8QFont font=QFontDialog::getFont(bool* ok, parent); // ok用于标记是否按下了“OK”按钮 bool ok; QFont font = QFontDialog::getFont(&ok, this); // 如果按下“OK”按钮,那么让“字体对话框”按钮使用新字体 // 如果按下“Cancel”按钮,那么输出信息 if (ok) ui->pushButton_3->setFont(font); else qDebug() << tr("没有选择字体!");输入对话框 QInputDialog
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19bool ok; // 当用户在QInputDialog对话框中按下OK键时,把bool ok设成ok=true,否则是,false // 获取字符串 QString string = QInputDialog::getText(this, tr("输入字符串对话框"), tr("请输入用户名:"), QLineEdit::Normal,tr("admin"), &ok); if(ok) qDebug() << "string:" << string; // 获取整数 int value1 = QInputDialog::getInt(this, tr("输入整数对话框"), tr("请输入-1000到1000之间的数值"), 100, -1000, 1000, 10, &ok); if(ok) qDebug() << "value1:" << value1; // 获取浮点数 double value2 = QInputDialog::getDouble(this, tr("输入浮点数对话框"), tr("请输入-1000到1000之间的数值"), 0.00, -1000, 1000, 2, &ok); if(ok) qDebug() << "value2:" << value2; QStringList items; items << tr("条目1") << tr("条目2"); // 获取条目 QString item = QInputDialog::getItem(this, tr("输入条目对话框"), tr("请选择或输入一个条目"), items, 0, true, &ok); if(ok) qDebug() << "item:" << item;消息对话框 QMessageBox
接口,很多
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25int ret=QMessageBox::question(parent,title,label_str="你了解这个问题吗",buttons=MessageBox::Ok,default_button=MessageBox::Ok); information(parent,title,label_str,buttons,default_button); warning(parent,title,label_str,buttons=MessageBox::Abort,default_button); critical(parent,title,label_str,buttons=MessageBox::YesAll,default_button); about(parent,title,label_str); // 问题对话框 int ret1 = QMessageBox::question(this, tr("问题对话框"), tr("你了解Qt吗?"), QMessageBox::Yes, QMessageBox::No); if(ret1 == QMessageBox::Yes) qDebug() << tr("问题!"); // 提示对话框 int ret2 = QMessageBox::information(this, tr("提示对话框"), tr("这是Qt书籍!"), QMessageBox::Ok); if(ret2 == QMessageBox::Ok) qDebug() << tr("提示!"); // 警告对话框 int ret3 = QMessageBox::warning(this, tr("警告对话框"), tr("不能提前结束!"), QMessageBox::Abort); if(ret3 == QMessageBox::Abort) qDebug() << tr("警告!"); // 错误对话框 int ret4 = QMessageBox::critical(this, tr("严重错误对话框"), tr("发现一个严重错误!现在要关闭所有文件!"), QMessageBox::YesAll); if(ret4 == QMessageBox::YesAll) qDebug() << tr("错误"); // 关于对话框 QMessageBox::about(this, tr("关于对话框"), tr("yafeilinux致力于Qt及Qt Creator的普及工作!"));返回类型,枚举型,QMessageBox::StandardButton 类型
- QMessageBox::Ok
- QMessageBox::Cancel
- QMessageBox::Close 等等
关于 buttons 参数,default_buttons 参数
buttons:
- 设置对话框会显示哪些按钮
default_buttons:
- 设置默认会选择的按钮,必须是 buttons 中设定好的
进度对话框 QProgressDialog
构造
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15QProgressDialog::QProgressDialog(const QString &labelText, const QString &cancelButtonText, int minimum, int maximum, QWidget *parent = nullptr, Qt::WindowFlags f = ...); QProgressDialog dialog(tr("文件复制进度"), tr("取消"), 0, 50000, this); dialog.setWindowTitle(tr("进度对话框")); // 设置窗口标题 dialog.setWindowModality(Qt::WindowModal); // 将对话框设置为模态 dialog.show(); for(int i=0; i<50000; i++) { // 演示复制进度 dialog.setValue(i); // 设置进度条的当前值 QCoreApplication::processEvents(); // 避免界面冻结 if(dialog.wasCanceled()) break; // 按下取消按钮则中断 } dialog.setValue(50000); // 这样才能显示100%,因为for循环中少加了一个数 qDebug() << tr("复制结束!");例子:
1 2 3 4 5 6 7 8 9 10 11 12QProgressDialog progress("Copying files...", "Abort Copy", 0, numFiles, this); progress.setWindowModality(Qt::WindowModal); progress.show(); for (int i = 0; i < numFiles; i++) { progress.setValue(i); //进度当前值 if (progress.wasCanceled()) break; //... copy one file } progress.setValue(numFiles);//由for循环少加了1,这样才能显示100%重要函数与方法:
- dialog->setValue(value)
- dialog->wasCanceled()
QtCoreApplication::processEvents()
- 防止冻结界面
错误信息对话框 QErrerMessage
1 2 3QErrorDialog errordlg= new QErrorDialog(); errordlg->setWindowTitle(tr("错误信息对话框")); errordlg->showMessage(tr("这里是出错信息!"));向导对话框 QWizard
重要部分
- 方法:wizard->addPage(QWizardPage* page)
- 类型:QWizardPage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29QWizardPage * MyWidget::createPage1() // 向导页面1 { QWizardPage *page = new QWizardPage; page->setTitle(tr("介绍")); return page; } QWizardPage * MyWidget::createPage2() // 向导页面2 { QWizardPage *page = new QWizardPage; page->setTitle(tr("用户选择信息")); return page; } QWizardPage * MyWidget::createPage3() // 向导页面3 { QWizardPage *page = new QWizardPage; page->setTitle(tr("结束")); return page; } // 向导对话框 void MyWidget::on_pushButton_8_clicked() { QWizard wizard(this); wizard.setWindowTitle(tr("向导对话框")); wizard.addPage(createPage1()); // 添加向导页面 wizard.addPage(createPage2()); wizard.addPage(createPage3()); wizard.exec(); }- 注:以上这些对话框类,最好直接查询 Help Mode,static method,property
对话框的共性
共同方法:
- setWindowTitle()
setOption(), setOptions()
- 每种对话框,都定义了一些枚举型,以设置几个特定选项
- 如:QColorDialog::QColorDialogOption 类型,QColorDialog::AlphaChanel
- 模态
对于需要显示文本信息的对话框
setText()
- QMessageBox 输出文本
- setLabel
setLabelText
- QInputDialog
- QProgressDialog
图片类
QMovie
作用:
存放.gif 文件
1 2 3QMovie *movie = new QMovie("F:/donghua.gif"); ui->label->setMovie(movie); // 在标签中添加动画 movie->start();
QPixmap
作用:
存放.png 文件
1ui->label->setPixmap(QPixmap("F:/logo.png"));
QLineEdit
自动补全功能
实现方式:使用 QCompleter 类
1 2 3 4 5 6 7QStringList wordList; wordList << "Qt" << "Qt Creator" << tr("你好"); // 新建自动完成器 QCompleter *completer = new QCompleter(wordList, this); // 设置大小写不敏感 completer->setCaseSensitivity(Qt::CaseInsensitive); ui->lineEdit4->setCompleter(completer);
数值设定
QAbstractSpinBox:抽象基类
- 目的:提供一个数值设定框和一个行编辑器来显示数值
QDateTimeEdit(日期时间设定)
QSpinBox(整数设定)
QDoubleSpinBox(浮点数的设定)
QDateTimeEdit
| |
滑块部件
QAbstractSlider 类
目的:
- 提供了一个区间内的整数值,它有一个滑块,可以定位到一个整数区间的任意值。
QScrollBar
滚动条 QScrollBar 更多的是用在 QScrollArea 类中来实现滚动区域;
QSlider
而 QSlider 是我们最常见的音量控制或多媒体播放进度等滑块;
QDial
是一个刻度表盘。
信号与槽
教程:
- PyQt6 Signals and Slots - CodersLegacy
本质:
- 信号与槽都是函数
QObject::connect 两种连接方法
- 函数指针法
SIGNAL 和 SLOT 宏 修饰法
有默认参数时
- singal 参数数量必须 >= slot 参数数量
特性
信号 signal
- 必须和 slot 函数接口一致
槽 slot
- 函数接口 可以有 比 slot 更多的默认参数
定义
- 都是 public 方法
定义位置
- 只能在头文件中(原因:sigal 由
moc生成, 即 Meta Object Compiler)
- 只能在头文件中(原因:sigal 由
返回值
- void, 即没有返回值
参数类型
最好是常用类型
- 方便 signal 和 slot 的重用性
调用位置
signal
- 推荐:定义类内部或子类
slot 调用顺序
- 按 connect 注册顺序
性能
与 callback 回调函数 比较
- 更灵活,但是更慢(有 overhead)
发送 signal
使用
emit 语句1 2 3 4 5 6 7void Counter::setValue(int value) { if (value != m_value) { m_value = value; emit valueChanged(value); // 这是信号 signal } }
激活
- 由 emit 语句触发
emit 语句 存放在某个函数中
- 这样 调用某个函数(或赋值语句等等),就会在后台 发出 emit signal
本质
- 执行一个函数,触发执行,一个或多个注册关联(connect)的 其他函数
- 回调函数,执行完成后,再接着执行的函数(参数表一致)
sender, reciever 用途
- singal 和 slot 各自的执行环境,上下文
- 说明执行线程
context thread
获取 sender 对象
QObject::sender()注意
- 只有在作用 slot 使用的函数 被 signal 激发时才有效,否则返回 nullptr
信号
注意
- 只需要声明即可
定义
- 由 moc 模块自动生成
槽
定义
1 2public slots: void showChildDialog();要加上 slots
- Qt5 中不加也可,但推荐加上
- public 表示在类外部也可使用它
连接信号与槽
使用 connect()函数
位置
- 在 QObject 中定义
函数接口
1 2 3 4 5QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)- connect(ui->showChildButton, &QPushButton::clicked, this, &MyWidget::showChildDialog);
- QPushButton::clicked()信号在 QPushButton 类中定义
四个参数:
- 发送者对象 sender
- 发送的信号 signal
- 接收者对象 receiver
- 要执行的槽 method
用法
直接使用
直接写函数名
1connect(sender, &QObject::destroyed, this, &MyObject::objectDestroyed);
使用宏修饰函数
使用
SIGNAL和SLOT宏使用环境
- 有默认参数
- signal 比 slot 有相同或更多的参数 (args_signal >= args_slot)
例子
1 2 3connect(sender, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(Qbject*))); connect(sender, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed())); connect(sender, SIGNAL(destroyed()), this, SLOT(objectDestroyed()));
注意
- slot 和 signal 参数数量 compiler 不会检测
自定义类型 作 signal 和 slot 参数
- 需要注册 Qt,以前 Qt 能在运行时 contruct, destruct, copy
- 参考:qRegisterMetaType的使用_wadfji 的博客-CSDN博客_qregistermetatype
- QMetaType
qRegisterMetaType<MyType>(const char* "MyType")要求
- type 必须满足 rule of three (constructor, copy constructor, destructor)
- 指针:指向的内容满足 rule of three
- typedef 类型
qRegisterMetaType<MyType>()- 无参数
要求
- 用于被宏函数
Q_DECLARE_METATYPE()修饰过的类型
- 用于被宏函数
使用 Qt Creator 的设计模式 Design mode
进入编辑信号和槽模式的方法
使用按钮
- 设计模式顶上工具栏中的按钮
使用快捷键
- 快捷键:F4
关联方法:
- 鼠标拖拽
自动关联
特点:
- 不用手动设置 connect 关联
- Qt 自动处理
- 因此,源代码里找不到 connect 函数
原理:
- 自动生成与 sender,signal 对应名称的槽函数
- 自动生成对应的 connect 函数语句
方法:
- 在设计模式中,右键发出信号的 widget,sender
选择“转到槽”(Go to slot…)
1 2 3 4void MyDialog::on_pushButton_clicked() { accept(); }命名方式:
- 如:on_pushButton_clicked()
名字组成
- on
- sender 信号发出者
- signal 信号
信号发送者
QObject::sender()- 在 slot 函数中,获取当前 thread 内部的信号 signal 发送者
- 注意: 不可是其它线程中的信号发送者
事件 Event
参考:
产生:
- 一个事件发生,Qt 就会生成一个
QEvent事件对象 - 这个事件由接收者的
QObject::event(QEvent*)方法处理
机制:
QObject::event(QEvent *e)- 不直接处理事件,把事件的处理分发给其它函数
QTimerEvent 定时发生的事件
参考:
特点:
- 每隔一个
interval时间段就会发生
触发:
QObject::startTimer(int interval)启动
处理:
QObject::timerEvent(QTimerEvent*)接收处理
QTimer 类, 计时器
更改对象名
- widget->setObjectName(QStringLiteral("newname"))
QDebug
两种用法
类似 printf
- qDebug("x: %d", x)
类似 cout
- qDebug()<<x<<str<<endl;
- 这种用法要加头文件#include<QDebug>
输出位置
- Qt Creator 的应用程序输出
布局 Layout
主要函数
- layout.addWidget()
- layout.addLayout()
layout.addStretch(int)
- 作用:添加暂为空白符(空白空间)
- 参考:PyQt布局之【QHBoxLayout、QVBoxLayout——表单布局】_jxwzh 的博客-CSDN博客
参数
- 默认值 0
- 0 或 1
- 当只有一个,或都是 1,或都是 0 时,无区别
- 有 1 有 0 时,0 不占用空间,1 仍然生效
QLayout
基类:
- QObject
- QLayoutItem
称呼:
- 布局管理器
具体布局类型
- QStackedLayout
- QGridLayout
- QFormLayout
QBoxLayout
- 子类型
QHBoxLayout
- QVBoxLayout
选定布局管理器
- QWidget::setLayout()
QHBoxLayout
| |
QGridLayout
| |
设置部件大小
名词:
- hint:原意暗示,此处意为建议的 recommended
两个大小属性(QWidget)
属性
- sizeHint
- minimumSizeHint
获取方法:对应的函数形式
- sizeHint()
- minimumSizeHint()
设置方法: set 形式
- setSizeHint()
- setMinimumSizeHint()
名词
splash screen
- 启动画面,版权页,溅射屏幕
进入 Qt 帮助模式教程
- 搜索 Qt overview,进入总教程
- 搜索 User Interfaces,进入 UI 教程
ui 文件
编译 uic
作用
- 把 ui 文件转换城头文件
命令调用
1uic -o ui_hellodialog.h hellodialog.ui
头文件
自动生成的头文件 ui_hellodialog.h
| |
使用自动生成的头文件
| |
相关的三个类
UI form 自动生成类 Ui_HelloDialog
- 定义与声明在 QT 命名空间对之间
放入到 namespace Ui 中的 Ui::HelloDialog
- 继承自 Ui_HelloDialog
- 为了名称好看,使用命名空间进行包装
- 可以外部使用了通过头文件 ui_hellodialog.h
定义与声明在 QT 命名空间对之间
- QT_BEGIN_NAMESPACE
- QT_END_NAMESPACE
全局类 HelloDialog
- 通过 has a 关系,内部绑定了 Ui::HelloDialog 类
- 裸露在外,全局类型,不在命名空间中
- 通过 QT_OBJECT 宏定义
解说
添加一个 ui 文件
- hellodialog.h
自动生成其余三个文件
- ui_hellodialog.h 和 hellodialog.h 与 helloworld.cpp
hellodialog.h
- 不使用#include"ui_hellodialog.h"
- 因为使用的只是 Ui::HelloDialog 的声明
hellodialog.cpp
- 必须使用#include"ui_hellodialog.h"
- 因为这里是使用了 Ui::HelloDialog 的实现内容
Qt Quick
QML Item
transform 变形功能
scale 放缩
- 沿一个点放缩
- 沿一个轴防缩
rotate 旋转
- 沿一个点旋转 Origin
- 沿一个轴旋转 Axis
translate 平移
pimpl 手法
- 参考:QT namespace UI_hebbely 的博客-CSDN博客
解释
- point to implementation, 指向实现的指针
作用
消除传统偶合 编程
eg:
1 2 3 4 5 6 7 8 9 10 11 12 13MyType c = MyType(); MyType *c = new MyType(); // c.hpp 文件 #include<x.hpp> class C { public: void f1(); private: X x; //与X的强耦合 };- 每一次编译,x.hpp 更改, c.hpp 都会重新编译
机理
eg:
1 2 3 4 5 6 7 8//c.hpp class X; //用前导声明取代include class C { ... private: X* pImpl; //声明一个X*的时候,class X不用完全定义 };class C 的 访问者只能访问到 C 的 接口,
- 访问不到 X 的 接口,起到了隔绝作用
总结
- 三个类 X, C, S
- C 的实现依赖 X
- 但是做到 C 的 接口不依赖 X
- 这样 X 的 更改 不会影响 S
本质
- 在 一处 声明变量(类)
- 在 另一处 定义这个变量(类)
图表
- 参考:QTCharts入门 使用QChartView做折线图_baizy77 的专栏-CSDN博客_qchartview
- 坐标图象
QChart :: 组织 图像组成部分
组成部分
- QAbstractAsix
坐标轴
- 实现:QValueAsis
- QAbstractSeries
图像数据 x,y 坐标数据
- 实现:QLineSeries
- Lagend
- 图例
- QChartView :: 负责显示图像
表格
- 参考:Qt深入浅出(十五)QTableView_qq769651718 的专栏-CSDN博客_qtableview
- MVC 设计
相关类
- QTableView
- QStandardItem
QtCore
QString
方法:
运算符
- +,+=
索引
- at(index)
查询
indexOf(str, from)
- //返回找到 str 的 index, from 是开始寻找的位置, 返回-1 表示没找到
lastIndexOf(str, from)
- //str 最后出现的位置
各处插入
str.insert(index,str2)
- str="zg";str.insert(1,"yl");//str==zylg
pend
- str.append(str2)
- str.prepend(str2)
push
- str.push_back(str)
- str.push_front(str)
删除
- remove(str, Qt::CaseInsensitive)//删除所有出现的 str
- remove(index, len)//从 index 开始的 len 个
清空
- clear()
格式化字符串
- QString("%1 is %2").arg(value).arg(value)
- str.sprintf("%s, %s", str2,str3)
替换
- str.replace(index,len,str2)
- str.replace(QRexExp& rx, str2)
- str.replace(QRegularExpression& re, str2)
- 修剪
作用于 str 本身
- str.trimed()
- str.simplified()//去掉空白,单个空白代替
- str.truncate(len)//只留前面 len 个
- str.chop(n)//去掉右边的 n 个
返回新 QString,substring
- str.left(n)//返回左边 n 个
- str.right(n)
- str.mid(index,len)//从 index 开始的 len 个
- str.mid(index)//从 index 开始的剩余部分
- str.chopped(len)//左边 len 个
判断
- str.startsWith("zy",Qt::CaseInsensitive);
- str.endsWith("zy",Qt::CaseInsensitive);
- str.contains("zy",Qt::CaseInsensitive);//return bool
- str.isNull() –> QChar.isNull()
- str.isEmpty()
转换
str.toInt()
- str="125"; long hex=str.toInt(&ok,16);//ok=true,hex=293
str.fill(char,n)//转换成 n 个 char
- str.fill("A",2) //str="AA"
数字变成 QString
- str.setNum(int)//把 int 变成 QString,存入 str
QString::number(value) //返回字符串,静态方法
QString::number(int,int base=10)
- QString s = QString::number(a, 16);// s == "3f"
- QString::number(double)
比较
str.compare(str_other, Qt::CaseInsensitive)
- Qt::Sensitive
- Qt::Sensitive
切割 section
str.section(char_seperator, start_index, end_index)
1 2 3 4 5 6 7QString csv = "forename,middlename,surname,phone"; QString path = "/usr/local/bin/myapp"; // First field is empty QString::SectionFlag flag = QString::SectionSkipEmpty; str = csv.section(',', 2, 2); // str == "surname" str = path.section('/', 3, 4); // str == "bin/myapp" str = path.section('/', 3, 3, flag); // str == "myapp"
迭代器 QString::iterator 类型
- begin()
- end()//指向 index=size(),即最后一个元素的后面,越界一个元素
- rbegin()//逆序第一个
- rend()
cbegin()//对应常量指针类型,不可改变*cbegin(),
- 返回类型 QString::const_iterator
- cend()
- constBegin()
- constEnd()
- crbegin()
- crend()
计数
- count(char)
- count(str)
- count(QRegExp &rx)
- count(QRegularExpression &re)
标准 C 字符串
- QChar* data()
大小写
- toUpper()
- toLower()
QChar
方法
判断
- isLetter()
- isNumber()不只是 10 个阿拉伯数字
- isDigit()只是阿拉伯数字
- isLower()
- isUpper()
- isTtileCase()
- isNull()
- isPunct()
- isSpace()
- isPrint()
Unicode
- isSurrogate()用于判断是否输入 Surrogate Range 范围内,Unicode 概念
- isHighSurrogate()
- isLowerSurrogate()
- isSymbol() 不懂
其他
- digitValue()对应的数值 int
- category()所属类型
- direction()特殊语言,如阿拉伯语,书写方向
QDir 和 QFile
- QDir 用来路径操纵
- QFile 用来 IO 读写
QVariant
QStringList
例子
1 2QStringList wordList; wordList << "Qt" << "Qt Creator" << tr("你好");
QRect
尺寸函数:
- x()
- y()
- width()
- height()
哪些是返回 QRect 类型的
- geometry()
- frameGeometry()
QSize
尺寸函数:只有宽和高
- width()
- height()
返回 QSize 类型的函数
- size()
容器
QGroupBox 组合框
- 布局参考:QGroupBox使用总结_fanyun 的博客-CSDN博客_qgroupbox
- 带绘制出外边框和 Title 的分组容器
属性
- name
- title
- font
checkable: bool
- 提供一个 选择框
checked: bool
- checked is True, 子部件才能被 enabled (accessible)
- False, 子部件不能被访问
可以容纳多个 widget
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15# pyqt5 groupBox = QGroupBox("Exclusive Radio Buttons") radio1 = QRadioButton("&Radio button 1") radio2 = QRadioButton("R&adio button 2") radio3 = QRadioButton("Ra&dio button 3") radio1.setChecked(True) vbox = QVBoxLayout() vbox.addWidget(radio1) vbox.addWidget(radio2) vbox.addWidget(radio3) vbox.addStretch(1)
QScrollArea 滚动区
作用
给 子 Widget 添加滚动条
- 当 容纳不下 内部子 Widget 时,显示滚动条
属性
- name
- font
函数
- addWidget()
- setBackgroundRole()
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24from xinet import QtWidgets, QtCore, QtGui from xinet.run_qt import run class ImageView(QtWidgets.QScrollArea): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 载入图片 imageLabel = QtWidgets.QLabel(self) image = QtGui.QPixmap("test.jpg") imageLabel.setPixmap(image) # 设定滚动条组件 self.setBackgroundRole(QtGui.QPalette.Dark) self.setWidget(imageLabel) # 初始化设定 self.init_Ui() def init_Ui(self): # 修改窗口默认尺寸 self.resize(500, 500) if __name__ == '__main__': run(ImageView)
QToolBox
作用
- 可隐藏式 多部件 分组
属性
- name
- font
currentIndex
- 当前活动页
活动标签
- itemLabel
- itemName
- itemBackgroundModel
方法
- addItem(QWidget, …)
- count() const
- currentIndex() const
- currentItem() const
- indexOf(QWidget)
- insertItem(index, widget, …)
- item(index)
- setCurrentIndex
- setCurrentItem
- setItemLabel
- 效果示例:Qt学习10——工具盒类QToolBox_shawn06-CSDN博客_qtoolbox
解说:
- 可包含多个子部件
显示方式
每一个子部件 –> 一个 按钮
按钮展示
- 按钮可以有:文字 + Icon
主体内容暂时
- 点击按钮实现
- 隐藏 + 展示 两种状态
QTabWidget
作用
- 通过 tab 标签选择展示组合中的一个标签 Wiget
属性
- name
- currentPage
- margin
tabShape
- 标签 shape
活动标签
- pageName
- pageTitle
函数
- addTab(widget, …)
- setMovable(bool)
- setTabEnabled(index, bool)
- QWidget* currentPage()
- int currentPageIndex()
QStackedWidget
- 使用参考:Qt之QStackedWidget多界面切换_onehappycoder-CSDN博客_qstackedwidget
功能
- 用于实现类似 ppt 幻灯片功能
- 一次只显示一个子 widget
属性
- name
- font
- currentPage
- pageName
方法
- addWidget
- count() const
- currentIndex() const
- currentWidget() const
- indexOf
槽函数
- setCurrentIndex(int index)
- setCurrentWidget(QWidget*)
QFrame
功能
- 基础分组部件
属性
- name
framesShape
- 边框形状
QFrame::Shape 枚举类型,形状
- QFrame::NoFrame
- QFrame::Box
- Panel 平板 对阴影起衬托作用
- WinPanel windows 风格 panel
- HLine 水平线,用于分割,不框住任何东西
- VLine 垂直线
- StyledPanel 使用 QStyle::drawPannel
framesShadow
- 边框阴影特性
QFrame::Shadow 阴影类型,枚举
- QFrame::Plain 和周围一样高
- QFrame::Raised 凸起
- QFrame::Sunken 凹陷
- QFrame::MShadow 内部的,对于阴影的掩码
QWidget
功能
- 基础类
- 本身不可见
- 可以包含子部件,删除 QWidget 时,子部件一起删除
属性
- name
- font
- cursor 光标样式
方法
childAt(x, y, bool includeThis=False)
- (x, y) 处的子部件
重载
- childAt(Point &p, bool includeThis=False)
- drawText(x, y, const QString& str)
QMdiArea
- 参考:QMdiArea Class | Qt Widgets 5.15.5
- 实现效果参考:Qt之容器控件(QMdiArea)_Shijia Yin-CSDN博客_qmdiarea
MDI: multiple document interface 多文档界面,多文件参与的窗口
- 对比 QMainWindow(SDI, single document interface) 单文件参与窗口
功能
- 多文档处理
- 内部多子窗口
属性
- name
- font
viewMode 视图模式
- TabbedView 或 SubWindowView
documentMode
- 保存的标签栏在选项卡视图模式是否设置为文件的模式,默认为 false
viewMode == TabbedView 时
- tabShape
- tabPosition
方法
- addSubWindow(QWidget*, …)
- removeSubWindow(QWidget*)
- setBackground(QBrush(Q::green))
- activeSubWindow() const
- QMdiSubWindow* currentSubWindow()
- setActiveSubWindow(QMdiSubWindow*)
槽
切换窗口
- activateNextSubWindow()
- activatePreviousSubWindow()
- setActiveWindow(QWidget*)
排布窗口
- cascadeSubWindows()
- tileSubWoindows
关闭
- closeActiveSubWindow()
- closeAllSubWindows()
信号
- subWindowActivated(QMdiSubWindow *window)
QDockWidget
- 使用参考:QDockWidget详解_chenlong12580 的专栏-CSDN博客_qdockwidget
- 效果:QDockWidget嵌套布局详解
功能
- 停靠窗体
属性
- name
- font
floating
- 是否可以 float
feature
- 参考:QDockWidget 停靠特征解说 | Qt Widgets 5.15.5
QDockWidget::DockWidgetFeatures 枚举类型,停靠特征
- QDockWidget::DockWidgetClosable
- QDockWidget::DockWidgetMovable
- QDockWidget::DockWidgetFloatable
- QDockWidget::DockWidgetVerticalTitleBar
- QDockWidget::AllDockWidgetFeatures
- QDockWidget::NoDockWidgetFeatures
allowedArea
- 可停靠区域
枚举类型 Qt::DockWidgetArea
- Qt::LeftDockWidgetArea 左
- Qt::RightDockWidgetArea 右
- Qt::TopDockWidgetArea 上
- Qt::BottomDockWidgetAreas 下
- Qt::AllDockWidgetArea (默认值)所有四个区域
- Qt::NoDockWidgetArea 不可停靠
windowTitle
- 停靠窗体 title
dockWidgetArea (Qt 官方没有)
- 停靠的区域
docked (Qt 官方没有)
- 停靠状态
函数
- setWidget(QWidget*) 设置内部子部件
- setFeatures(features)
- setFloating(bool)
setTitleBarWidget(QWidget*)
- 自定义标题栏 Widget
- 设置 nullptr, 恢复默认样式
按钮类部件
QAbstractButton
作用:
- Button 类的抽象基类,提供按钮的通用功能
按钮类型
标准按钮 QPushButton
设置文本
添加快捷键
- 在对应字母前添加&符号
调用方法:Alt + 给定字母
1 2 3 4 5 6 7ui->pushBtn1->setText(tr("&nihao")); // 这样便指定了Alt+N为加速键 ui->pushBtn2->setText(tr("帮助(&H)")); ui->pushBtn2->setIcon(QIcon("../image/help.png")); ui->pushBtn3->setText(tr("z&oom")); QMenu *menu = new QMenu(this); menu->addAction(QIcon("../image/zoom-in.png"), tr("放大")); ui->pushBtn3->setMenu(menu);
复选框 QCheckBox
功能
- 提供对号框
单选框按钮 QRadioButton
功能
- 多选一列表
特点
在一个容器或布局内,自动互斥
- 互斥:点击一个 radio, 另一个就会取消选中
工具按钮 QToolButton。
功能
- 用在 ToolBar 中的按钮
- 可以添加 action, 可以显示图片 icon
QCommandLinkButton
功能
- 多选一功能按钮
QDialogButtonBox
参考:
功能
- QDiaglog 用来快速添加多个按钮
属性
centerButtons: bool
- 是否居中
orientation: Qt::Orientation
- 方向,水平还是竖直
standardButtons: QStandardButton
- 按钮有哪些
函数
添加单个 button
addButton(…)
- 重载多,添加单个 button
设置多个 button
- setStandarButtons(QStandardButton buttons)
判断
QStandardButton standardButton(QAbstractButton* button) const- 判断 给定 button 的 QStandardButton 枚举类型
QDialogButtonBox::ButtonRole buttonRole(QAbstractButton *button) const- 判断 QDialogButtonBox::QButtonRole 枚举类型
方位给定 按钮
- box->button(button_type)
button 类型
QDialogButtonBox::QStandardButton枚举类型- 内部实际存储:
QAbstractButton*指针类型
信号
- clicked(QAbstractButton* button)
点击后,判断是哪个按钮被按下
- 通过信号 clicked(QAbstractButton*)
判断传过来的是什么 button 类型即可
快捷判断
信号
- accepted()
- helpRequested()
- rejected()
练习实现, PySide6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45from PySide6.QtCore import Qt, Slot from PySide6.QtWidgets import ( QApplication, QDialogButtonBox, QDialog, QAbstractButton, QLabel, QVBoxLayout ) class Window(QDialog): def __init__(self): super().__init__() self.initUI() def initUI(self): self.box = QDialogButtonBox(self) self.box.setStandardButtons(QDialogButtonBox.StandardButton.Abort | QDialogButtonBox.Apply | QDialogButtonBox.Help) self.box.setOrientation(Qt.Orientation.Vertical) self.label = QLabel("init text", self) self.vlayout = QVBoxLayout(self) self.vlayout.addWidget(self.label) self.vlayout.addStretch(1) self.vlayout.addWidget(self.box) self.setLayout(self.vlayout) self.box.clicked.connect(self.onClickedButton) def onClickedButton(self, button: QAbstractButton): msg = '%s been clicked' if self.box.standardButton(button) == QDialogButtonBox.Help: self.label.setText(msg % "help") elif self.box.buttonRole(button) == QDialogButtonBox.ApplyRole: self.label.setText(msg % "apply role") elif self.box.standardButton(button) == QDialogButtonBox.Abort: self.label.setText(msg % "abort") else: self.label.setText(msg % "Nothing") def main(): app = QApplication() w = Window() w.show() app.exec()
视图
QAbstractItemView
要点功能
- 选择
- 滚动
- 拖拽
显示和编辑
- setItemDelegate()
- model 操作
继承
- 继承子类只要实现特定功能相关相关功能方法即可
属性
滚动
- autoScroll: bool
- autoScrollMargin: int
拖动
- dragEnabled: bool
- dragDropMode
编辑
editTriggers: QAbstractItemView::editTriggers
- 哪些类型按键会激发编辑功能
方法
index
- rootIndex()
- currentIndex()
QListView
功能
- 展示 文字列表 或 Icon 列表
子类
QListWidget
- QListView 需要自己创建设置 Model
- QListWidget 内建 Model,用户 addItem()即可
显示图片
QLabel.setPixelmap()例子
1 2 3imageLabel = QtWidgets.QLabel(self) image = QtGui.QPixmap("test.jpg") imageLabel.setPixmap(image)
PySide6
signals 和 slots 相关问题
连接:
QtCore.SINGALQtCore.SLOTQtCore.QObject.connect
定义
- 装饰器声明重载函数接口
QtCore.SignalQtCore.Slot
连接 connect
使用 connect
通过信号调用
1self.clicked.connect(other, other.slot_function)通过 QObject.connect
1 2 3from PySide6 import QtWidgets, QtCore QtCore.connect(boxA, boxA.clicked, window, window.onMywindowClicked)使用 SIGNAL, SLOT 宏
1 2 3 4from PySide6.QtCore import SIGNAL, SLOT QObject.connect(scrollBar, SIGNAL(valueChanged(int)), label, SLOT(setNum(int)))
定义 singals 和 slots, 重载问题
定义 信号 与 槽
使用 QtCore.Signal 类 和 QtCore.Slot 类
1 2 3 4 5class Foo(QObject): @Slot(float, result=int) def getFloatReturnInt(self, f): return int(f)Signal 类
方法
- connect
- disconnect
emit(*args)
- args – 信号的相关参数
- eg:
heySignal.emit("hello there")
构造 – 创建 信号
1 2 3class Communicate(QObject): # create a new signal on the fly and name it 'speak' speak = Signal(str)- 直接创建,无需定义
信号
特点
形式
过去时单次
- clicked
- pressed
- released
- valueChanged
意义
- 不执行特殊动作,通过 slot 执行动作
- 只是表示一个事件的发生
函数接口
- 无返回值
PyQt6
signals 和 slots
pyqt6 自定义 singal 机制和 PySide6 不同
定义 signals
- 通过 pyqtSignal 类实现
| |
注意
signal 对象只能是类属性
- 也就是说,在
__init__中创建的 signal 无效 正确例子
1 2 3 4 5 6 7from Qt.QtCore import pyqtSignal from Qt.QtWidgets import QWidget class MyApp(QWidget): closeSignal = pyqtSignal(str) def __init__(self): self.closeSignal.connect(self.close)错误例子
1 2 3 4 5 6 7from Qt.QtCore import pyqtSignal from Qt.QtWidgets import QWidget class MyApp(QWidget): def __init__(self): self.closeSignal = pyqtSignal(str) # 这样无效 self.closeSignal.connect(self.close)
- 也就是说,在
注意
QLayout 中的 addChildWidget() Vs addWidget() 不同
addChildWidget
- 在 addWidget 内部被调用
- 如果直接使用 addChildWidget 会造成添加的
widget不被显示
拖拽 dnd – Drag and Drop
参考:
QDrag::hotSpot
hotSpot()
- 拖拽时,背景图片 pixel_map 左上角相对光标的偏离位置
qt designer
pyqt6
注意:
需要额外安装
pip install pyqt6-tools
调用方式
1 2 3 4 5# qt designer pyqt6-tools designer # qt uic pyuic6
pyside6
FAQ
python + qt 如何隐藏 cmd prompt
python 代码
- 解决方法:使用 pythonw.exe
- eg: 使用
pythonw.exe main.py
pyinstaller + qt 代码
参考:
Using PyInstaller — PyInstaller 5.4.1 documentation
- -w
- –windowed
- –noconsole
解决方法:
- 使用 -w 等命令行参数
- 把 main.py 改成 main.pyw 在运行 pyinstaller
文章作者 Sawyer Zheng
上次更新 2022-09-19 (288a12d)