QtGUI模块功能详细说明,图标和光标(七)
目录
一.窗口和屏幕管理
二. 绘图和渲染
三. 图像处理
四. 字体和文本
五. 事件和输入处理
六. OpenGL 和硬件加速
七. 颜色和外观
八. 图标和光标
1、QIcon: 图标管理
1.1、QIcon 简介
1.2、图标的来源与创建
1.3、多分辨率与 DPI 支持
1.4、图标的状态管理
2、QCursor: 鼠标光标样式和自定义形状
2.1、QCursor 简介
2.2、预定义光标样式
2.3、自定义光标形状
2.4、光标的设置与管理
3、QIconEngine: 自定义图标渲染引擎
3.1、QIconEngine 简介
3.2、QIconEngine 的工作原理
3.3、实现自定义图标引擎
3.4、将自定义引擎与 QIcon 关联使用
九. 平台和渲染后端
十. 国际化(GUI 相关)
一. 窗口和屏幕管理
请跳转章节,此处不再重复:QtGUI模块功能详细说明,窗口和屏幕管理(一)
二. 绘图和渲染
请跳转章节,此处不再重复:QtGUI模块功能详细说明,图形绘制与渲染(二)
三. 图像处理
请跳转章节,此处不再重复:QtGUI模块功能详细说明,图像处理(三)
四. 字体和文本
请跳转章节,此处不再重复:QtGUI模块功能详细说明, 字体和文本渲染(四)
五. 事件和输入处理
请跳转章节,此处不再重复:QtGUI模块功能详细说明,事件与输入处理(五)
六. OpenGL 和硬件加速
支持 OpenGL 和 Vulkan 渲染,适用于高性能图形。暂不说明。
七. 颜色和外观
请跳转章节,此处不再重复:QtGUI模块功能详细说明,颜色和外观(六)
八. 图标和光标
1、QIcon: 图标管理
1.1、QIcon 简介
QIcon 是一个跨平台的图标管理工具,能够加载和显示图像(例如 PNG、JPG、SVG 等格式)作为应用程序中的视觉元素。QIcon 不直接存储图像数据,而是通过引用图像文件或资源来管理图标的显示。
-
多模式支持:QIcon 支持多种模式(如 QIcon::Normal、QIcon::Disabled、QIcon::Active、QIcon::Selected),允许为不同交互状态指定不同图像。
-
多状态支持:支持 On 和 Off 状态,常用于切换控件(如复选框或按钮)。
-
多种构造方式:可以通过文件路径、资源文件、QPixmap 或 QImage 创建 QIcon。
-
自动缩放:根据控件大小或高 DPI 设置,QIcon 能自动调整图标尺寸。
1.1.1、QIcon 在 Qt 部件中的应用
按钮(QPushButton、QToolButton 等)
-
QPushButton:通过 setIcon() 方法为按钮设置图标。
QPushButton *button = new QPushButton; QIcon icon(":/images/save.png"); // 从资源文件加载图标 button->setIcon(icon); button->setIconSize(QSize(24, 24)); // 设置图标大小
-
QToolButton:工具按钮通常只显示图标,不显示文本,QIcon 是其核心视觉元素。
QToolButton *toolButton = new QToolButton; toolButton->setIcon(QIcon(":/images/open.png"));
-
状态支持:QIcon 可以为按钮的不同状态(如禁用或按下)设置不同图标:
QIcon icon; icon.addFile(":/images/save_normal.png", QSize(), QIcon::Normal); icon.addFile(":/images/save_disabled.png", QSize(), QIcon::Disabled); button->setIcon(icon);
动作(QAction)
QAction 是 Qt 中用于表示菜单项、工具栏按钮等抽象动作的类,QIcon 为其提供视觉标识。
-
菜单项:在 QMenu 中,QAction 使用 QIcon 显示图标。
QAction *openAction = new QAction(QIcon(":/images/open.png"), "Open", this); QMenu *fileMenu = menuBar()->addMenu("File"); fileMenu->addAction(openAction);
-
工具栏:在 QToolBar 中,QAction 的图标由 QIcon 提供,点击工具栏按钮会触发相应的动作。
QToolBar *toolbar = addToolBar("Main Toolbar"); toolbar->addAction(openAction);
窗口图标(QMainWindow、QDialog 等)
QIcon 可用于设置窗口的标题栏图标或任务栏图标,增强应用程序的品牌识别:
-
设置窗口图标:
QMainWindow *window = new QMainWindow; window->setWindowIcon(QIcon(":/images/app_icon.png"));
-
系统托盘图标:在 QSystemTrayIcon 中,QIcon 用于显示托盘图标。
QSystemTrayIcon *trayIcon = new QSystemTrayIcon(QIcon(":/images/tray_icon.png"), this); trayIcon->show();
其他部件
-
QListWidget、QTreeWidget 等:QIcon 用于为列表项或树节点设置图标。
QListWidgetItem *item = new QListWidgetItem(QIcon(":/images/folder.png"), "Folder"); listWidget->addItem(item);
-
QTabBar/QTabWidget:为选项卡设置图标。
QTabWidget *tabWidget = new QTabWidget; tabWidget->addTab(new QWidget, QIcon(":/images/tab.png"), "Tab 1");
-
QLabel:虽然 QLabel 通常显示文本或图像,但可以通过 QIcon 转换为 QPixmap 显示图标。
QLabel *label = new QLabel; label->setPixmap(QIcon(":/images/icon.png").pixmap(32, 32));
1.2、图标的来源与创建
1.2.1、从文件加载(PNG, JPG, SVG 等格式)
QIcon 可以通过文件路径直接加载图像文件,支持多种常见格式,包括 PNG、JPG、SVG、ICO 等。
-
使用 QIcon 的构造函数或 addFile() 方法加载图像文件。
-
可以为不同状态(如 Normal、Disabled)或尺寸指定不同的图像文件。
// 简单加载单个图像文件
QIcon icon("path/to/icon.png"); // PNG 文件
QPushButton *button = new QPushButton;
button->setIcon(icon);// 为不同状态加载不同图像
QIcon multiStateIcon;
multiStateIcon.addFile("path/to/normal.png", QSize(), QIcon::Normal); // 正常状态
multiStateIcon.addFile("path/to/disabled.png", QSize(), QIcon::Disabled); // 禁用状态
button->setIcon(multiStateIcon);// 加载 SVG 文件(支持矢量缩放)
QIcon svgIcon("path/to/icon.svg");
button->setIcon(svgIcon);
1.2.2、从 QPixmap 或 QImage 创建
QIcon 可以通过 QPixmap 或 QImage 对象创建,适合需要动态生成图标或从内存中加载图像的场景。QPixmap 适用于与显示设备相关的像素数据,而 QImage 更适合图像处理。
-
使用 QIcon 的构造函数直接从 QPixmap 或 QImage 创建。
-
也可以通过 addPixmap() 方法为不同状态或模式添加图像。
// 从 QPixmap 创建
QPixmap pixmap(32, 32);
pixmap.fill(Qt::red); // 创建一个红色矩形
QIcon icon(pixmap);
QPushButton *button = new QPushButton;
button->setIcon(icon);// 从 QImage 创建
QImage image(32, 32, QImage::Format_ARGB32);
image.fill(Qt::blue); // 创建一个蓝色矩形
QIcon imageIcon(QPixmap::fromImage(image));
button->setIcon(imageIcon);// 为不同状态添加不同 QPixmap
QIcon multiIcon;
multiIcon.addPixmap(QPixmap("path/to/normal.png"), QIcon::Normal);
multiIcon.addPixmap(QPixmap("path/to/disabled.png"), QIcon::Disabled);
button->setIcon(multiIcon);
注意事项:
-
性能:QPixmap 与显示设备相关,适合直接渲染;QImage 更适合图像操作(如缩放、滤镜)。
-
格式转换:QImage 需通过 QPixmap::fromImage() 转换为 QPixmap 再创建 QIcon。
-
内存管理:QIcon 内部会对 QPixmap 或 QImage 进行深拷贝,确保原始对象的生命周期不会影响图标。
1.2.3、从 Qt 资源系统 (.qrc) 加载图标
Qt 资源系统允许将图像文件嵌入应用程序的可执行文件中,通过 .qrc 文件管理资源。QIcon 可以直接从资源路径加载图标,路径以 :/ 开头。这种方式适合打包应用程序,确保图标文件不会丢失。
-
创建 .qrc 文件(如 resources.qrc),列出资源文件。
-
使用 QIcon 构造函数或 addFile() 加载资源路径。
创建 .qrc 文件:可直接使用QtCreator 添加资源文件界面操作实现创建
<!DOCTYPE RCC>
<RCC version="1.0"><qresource><file>images/icon.png</file><file>images/icon_disabled.png</file></qresource>
</RCC>
编译资源:
在 Qt 项目文件(.pro)中添加:使用 qmake 或 CMake 编译,资源将被嵌入可执行文件。
RESOURCES += resources.qrc
// 加载单个资源图标
QIcon icon(":/images/icon.png");
QPushButton *button = new QPushButton;
button->setIcon(icon);// 为不同状态加载资源图标
QIcon multiIcon;
multiIcon.addFile(":/images/icon.png", QSize(), QIcon::Normal);
multiIcon.addFile(":/images/icon_disabled.png", QSize(), QIcon::Disabled);
button->setIcon(multiIcon);
1.2.4、QIcon 的拷贝和赋值语义
QIcon 是一个轻量级类,采用隐式共享(copy-on-write)机制,类似于 QString 和 QPixmap。这意味着拷贝和赋值操作非常高效,多个 QIcon 对象可以共享相同的底层数据,直到其中一个对象被修改。
-
拷贝构造:创建 QIcon 的副本时,共享相同的图像数据。
-
赋值操作:将一个 QIcon 赋值给另一个时,共享数据,引用计数增加。
-
修改操作:当修改 QIcon(如调用 addFile() 或 addPixmap())时,触发深拷贝,创建独立的数据副本。
// 拷贝构造
QIcon icon1(":/images/icon.png");
QIcon icon2(icon1); // 共享数据,高效
QPushButton *button1 = new QPushButton;
button1->setIcon(icon2); // 使用拷贝的图标// 赋值操作
QIcon icon3;
icon3 = icon1; // 共享数据
icon3.addFile(":/images/new_icon.png"); // 触发深拷贝,icon1 不受影响// 验证共享状态
qDebug() << icon1.isDetached(); // false(共享数据)
qDebug() << icon3.isDetached(); // true(深拷贝后独立)
1.3、多分辨率与 DPI 支持
1.3.1、为不同 DPI 提供多个尺寸的图像
为了支持高 DPI 显示,开发者可以为 QIcon 提供多个分辨率的图像版本(例如 1x、2x、3x),以适应不同的设备像素比。Qt 会根据屏幕的 DPR 和控件的需求尺寸选择最合适的图像。
-
使用 QIcon::addFile() 或 QIcon::addPixmap() 方法,为同一图标的不同分辨率指定图像。
-
通常通过文件名后缀(如 @2x、@3x)或显式指定尺寸来区分不同分辨率的图像。
-
资源文件或文件系统中的图像可以按分辨率组织。
// 为不同分辨率提供图像(通过文件)
QIcon icon;
icon.addFile(":/images/icon.png", QSize(16, 16)); // 1x,标准分辨率
icon.addFile(":/images/icon@2x.png", QSize(32, 32)); // 2x,高分辨率
icon.addFile(":/images/icon@3x.png", QSize(48, 48)); // 3x,超高分辨率
QPushButton *button = new QPushButton;
button->setIcon(icon);
button->setIconSize(QSize(16, 16)); // 控件期望的逻辑尺寸
使用 QPixmap: 如果图标是动态生成的,可以通过 QPixmap 指定不同分辨率:
QIcon icon;
QPixmap pixmap1x(16, 16);
pixmap1x.fill(Qt::red);
QPixmap pixmap2x(32, 32);
pixmap2x.fill(Qt::red);
icon.addPixmap(pixmap1x, QIcon::Normal, QIcon::Off); // 1x
icon.addPixmap(pixmap2x, QIcon::Normal, QIcon::Off); // 2x
QPushButton *button = new QPushButton;
button->setIcon(icon);
button->setIconSize(QSize(16, 16));
1.3.2、Qt 自动选择最佳尺寸图标的机制
Qt 的 QIcon 引擎会根据以下因素自动选择最合适的图标版本:
-
设备像素比(DPR):由 QScreen::devicePixelRatio() 或 QWindow::devicePixelRatio() 提供。
-
控件期望的图标尺寸:由 setIconSize() 或控件的默认尺寸(如按钮的 iconSize 属性)指定。
-
图标状态和模式:如 Normal、Disabled、Active 等。
-
可用图像的分辨率:QIcon 中注册的图像尺寸。
选择机制:
-
计算物理尺寸:
-
Qt 将控件期望的逻辑尺寸(QSize)乘以设备的 DPR,得到物理像素尺寸。
-
例如:控件设置 iconSize 为 16x16 像素,DPR 为 2.0,则 Qt 会寻找接近 32x32 像素的图像。
-
-
匹配最近尺寸:
-
Qt 从 QIcon 中注册的图像列表中选择与目标物理尺寸最接近的图像。
-
如果没有精确匹配,Qt 会选择尺寸稍大的图像并缩放到目标尺寸(以避免模糊)。
-
-
优先级:
-
优先选择与当前状态(如 Normal、Disabled)和模式匹配的图像。
-
如果没有特定状态的图像,Qt 会回退到默认状态(通常是 Normal)。
-
-
缩放处理:
-
如果选择的图像尺寸与目标尺寸不匹配,Qt 会使用高质量缩放算法(如平滑缩放)调整图像。
-
对于 SVG 图像,Qt 会直接渲染到目标尺寸,无需额外图像版本。
-
// 创建一个支持多分辨率的 QIcon
QIcon icon;
icon.addFile(":/images/icon.png", QSize(16, 16)); // 1x
icon.addFile(":/images/icon@2x.png", QSize(32, 32)); // 2x// 设置按钮图标
QPushButton *button = new QPushButton;
button->setIcon(icon);
button->setIconSize(QSize(16, 16)); // 逻辑尺寸// 假设设备 DPR = 2.0,Qt 将选择 32x32 的图像(icon@2x.png)
验证 DPR 和选择:
开发者可以通过以下代码检查设备的 DPR 和实际使用的图标尺寸:
qDebug() << "Device Pixel Ratio:" << button->window()->windowHandle()->devicePixelRatio();
QPixmap actualPixmap = icon.pixmap(button->iconSize(), QIcon::Normal);
qDebug() << "Selected Pixmap Size:" << actualPixmap.size();
1.4、图标的状态管理
QIcon 支持为不同的交互状态和控件状态提供不同的图像,从而增强用户界面的动态性和直观性。
1.4.1、QIcon::Mode:图标模式
QIcon::Mode 枚举定义了图标的视觉模式,用于表示控件在不同交互状态下的外观。Qt 会根据控件的状态(如启用、禁用、悬停等)自动选择对应的模式。
-
QIcon::Normal:默认模式,表示控件处于正常、启用状态。
-
QIcon::Disabled:禁用模式,表示控件不可交互(例如按钮被禁用)。
-
QIcon::Active:激活模式,通常在,
-
QIcon::Selected:选中模式,表示控件被选中(如在菜单或列表中选中某项)。
使用场景:
-
按钮在禁用时显示灰色图标(Disabled)。
-
工具栏按钮在悬停或点击时高亮显示(Active)。
-
菜单项选中时显示不同图标(Selected).
QIcon icon;
icon.addFile(":/images/button_normal.png", QSize(), QIcon::Normal); // 正常状态
icon.addFile(":/images/button_disabled.png", QSize(), QIcon::Disabled); // 禁用状态
icon.addFile(":/images/button_active.png", QSize(), QIcon::Active); // 激活状态
QPushButton *button = new QPushButton;
button->setIcon(icon);
button->setEnabled(false); // 禁用按钮,将显示 disabled 图标
1.4.2、QIcon::State:图标状态
QIcon::State 枚举定义了图标的开关状态,主要用于表示可切换控件(切换按钮)的两种状态。
-
QIcon::On:表示控件处于“开启”状态(如复选框被选中)。
-
QIcon::Off:表示控件处于“关闭”状态(如复选框未选中)。
#include <QApplication>
#include <QToolButton>
#include <QIcon>int main(int argc, char *argv[]) {QApplication app(argc, argv);QIcon icon;icon.addFile(":/images/checkbox_on.png", QSize(), QIcon::Normal, QIcon::On); // 选中状态icon.addFile(":/images/checkbox_off.png", QSize(), QIcon::Normal, QIcon::Off); // 未选中状态QToolButton *toggleButton = new QToolButton;toggleButton->setCheckable(true); // 启用切换状态toggleButton->setIcon(icon);toggleButton->setIconSize(QSize(16, 16));toggleButton->setText("Toggle");toggleButton->show();return app.exec();
}
2、QCursor: 鼠标光标样式和自定义形状
2.1、QCursor 简介
QCursor 用于表示和管理应用程序中的鼠标光标(cursor)。它提供了对光标形状、位置以及行为的控制,允许开发者自定义光标的外观和功能,以适应不同的用户交互场景。
-
设置光标形状:QCursor 允许开发者设置不同的光标形状,例如箭头(Qt::ArrowCursor)、十字(Qt::CrossCursor)、等待(Qt::WaitCursor)等。
-
自定义光标:开发者可以通过加载图像(如位图或图标)创建自定义光标形状,使用 QCursor(QPixmap) 构造函数加载自定义图像。
-
控制光标位置:QCursor 提供方法(如 QCursor::setPos() 和 QCursor::pos())来设置或获取鼠标光标的屏幕位置,常用于需要程序化控制光标移动的场景,如游戏或绘图应用。
-
动态光标管理:支持在特定控件或窗口区域内动态切换光标。通过 QWidget::setCursor() 设置某个控件的光标形状,或者通过 QApplication::setOverrideCursor() 全局覆盖光标。
2.1.1、关键方法与属性:
-
QCursor(Qt::CursorShape shape):基于预定义形状创建光标。
-
QCursor(const QPixmap &pixmap, int hotX = -1, int hotY = -1):基于自定义图像创建光标,指定热点位置。
-
QCursor::pos():获取当前光标在屏幕上的位置。
-
QCursor::setPos(int x, int y):将光标移动到指定屏幕坐标。
-
QWidget::setCursor(const QCursor &cursor):为特定控件设置光标。
-
QApplication::setOverrideCursor(const QCursor &cursor):临时覆盖全局光标。
-
QApplication::restoreOverrideCursor():恢复被覆盖的光标。
#include <QApplication>
#include <QWidget>
#include <QCursor>int main(int argc, char *argv[]) {QApplication app(argc, argv);QWidget window;// 设置窗口的光标为手形window.setCursor(QCursor(Qt::PointingHandCursor));// 全局设置等待光标QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));window.show();return app.exec();
}
2.2、预定义光标样式
2.2.1、Qt::CursorShape 枚举的各种标准光标样式
Qt::CursorShape 是 Qt 框架中定义的一个枚举类型,位于 Qt 命名空间内,用于指定预定义的鼠标光标形状。
-
Qt::ArrowCursor:
-
描述:标准的箭头光标,通常为一个向左上方倾斜的箭头。
-
用途:默认光标,用于表示普通选择或导航状态,适用于大多数非特定交互场景(如窗口背景、普通控件)。
-
典型场景:桌面应用程序的主窗口、文件浏览器中的非交互区域。
-
-
Qt::PointingHandCursor:
-
描述:手形光标,显示为一个指向的手指,通常表示可点击的元素。
-
用途:提示用户可以点击某个控件或区域,例如超链接、按钮或可交互的图标。
-
典型场景:Web 浏览器中的超链接、GUI 中的按钮。
-
-
Qt::IBeamCursor:
-
描述:I 形光标(或称文本光标),形似一个垂直的“I”或光标线。
-
用途:表示用户可以选择或编辑文本,常见于文本输入区域。
-
典型场景:文本编辑器、输入框(如 QLineEdit、QTextEdit)。
-
-
Qt::WaitCursor:
-
描述:等待光标,通常显示为沙漏(Windows)或旋转的圆圈(macOS/Linux)。
-
用途:提示用户程序正在执行耗时操作,暂时无法响应用户输入。
-
典型场景:文件加载、数据处理、网络请求期间。
-
-
Qt::BusyCursor:
-
描述:忙碌光标,通常与 Qt::WaitCursor 类似,但可能带有额外的箭头,表示程序忙碌但仍允许部分交互。
-
用途:用于程序忙碌但仍可接受某些输入的场景。
-
典型场景:后台任务运行时,允许用户继续操作其他控件。
-
-
Qt::CrossCursor:
-
描述:十字光标,显示为一个十字形。
-
用途:表示精确选择或定位,常见于绘图或设计工具中。
-
典型场景:图像编辑软件中的选择工具、CAD 软件中的定位操作。
-
-
Qt::OpenHandCursor:
-
描述:张开的手形光标,表示可以抓取或拖动。
-
用途:提示用户可以拖动对象或平移视图。
-
典型场景:地图应用程序中的平移操作、可拖动的界面元素。
-
-
Qt::ClosedHandCursor:
-
描述:握紧的手形光标,表示正在拖动或抓取。
-
用途:表示拖动操作正在进行,通常与 Qt::OpenHandCursor 配合使用。
-
典型场景:拖动窗口、调整图形元素时。
-
-
Qt::SizeVerCursor:
-
描述:垂直双向箭头光标,表示可以上下调整大小。
-
用途:提示用户可以调整控件或窗口的垂直尺寸。
-
典型场景:调整窗口高度、表格行高。
-
-
Qt::SizeHorCursor:
-
描述:水平双向箭头光标,表示可以左右调整大小。
-
用途:提示用户可以调整控件或窗口的水平尺寸。
-
典型场景:调整窗口宽度、表格列宽。
-
-
Qt::SizeFDiagCursor:
-
描述:对角线双向箭头光标(从左上到右下),表示可以沿对角线调整大小。
-
用途:提示用户可以同时调整宽度和高度。
-
典型场景:调整窗口的右下角大小。
-
-
Qt::SizeBDiagCursor:
-
描述:对角线双向箭头光标(从右上到左下),表示可以沿另一对角线调整大小。
-
用途:与 Qt::SizeFDiagCursor 类似,用于调整窗口或控件大小。
-
典型场景:调整窗口的左下角或右上角。
-
-
Qt::UpArrowCursor:
-
描述:向上箭头光标。
-
用途:较少使用,通常用于特定场景,如表示向上选择或导航。
-
典型场景:自定义工具栏或导航控件。
-
-
Qt::BlankCursor:
-
描述:空光标,即隐藏光标。
-
用途:用于完全隐藏光标,常见于全屏游戏或触摸屏应用。
-
典型场景:第一人称射击游戏、视频播放器。
-
-
Qt::DragMoveCursor:
-
描述:表示移动操作的光标,通常为一个箭头加四向箭头图标。
-
用途:提示用户正在执行拖放操作中的移动。
-
典型场景:文件拖放到新文件夹、拖动界面元素。
-
-
Qt::DragCopyCursor:
-
描述:表示复制操作的光标,通常为一个箭头加加号图标。
-
用途:提示用户正在执行拖放操作中的复制。
-
典型场景:文件复制到新位置。
-
-
Qt::ForbiddenCursor:
-
描述:禁止光标,通常为一个圆形加斜杠。
-
用途:提示用户当前操作不被允许。
-
典型场景:尝试将文件拖放到不可写入的区域。
-
2.2.2、如何设置标准光标到部件或应用程序
Qt 提供了灵活的方式来设置标准光标样式,可以针对特定部件(QWidget 及其子类)或整个应用程序进行设置。
为特定部件设置光标
通过 QWidget::setCursor() 方法,可以为特定的控件或窗口设置光标样式。当鼠标进入该控件区域时,光标会自动切换为指定的形状。
#include <QApplication>
#include <QPushButton>
#include <QVBoxLayout>int main(int argc, char *argv[]) {QApplication app(argc, argv);// 创建主窗口QWidget window;QVBoxLayout *layout = new QVBoxLayout(&window);// 创建按钮并设置不同的光标样式QPushButton *button1 = new QPushButton("Click Me");button1->setCursor(QCursor(Qt::PointingHandCursor)); // 手形光标QPushButton *button2 = new QPushButton("Edit Text");button2->setCursor(QCursor(Qt::IBeamCursor)); // 文本光标// 添加按钮到布局layout->addWidget(button1);layout->addWidget(button2);window.setLayout(layout);window.show();return app.exec();
}
为整个应用程序设置全局光标
通过 QApplication::setOverrideCursor() 方法,可以临时覆盖整个应用程序的光标样式。这种方法适合在程序执行特定任务(如耗时操作)时统一显示光标。
#include <QApplication>
#include <QPushButton>
#include <QTimer>int main(int argc, char *argv[]) {QApplication app(argc, argv);// 创建主窗口和按钮QWidget window;QPushButton *button = new QPushButton("Start Long Task", &window);// 按钮点击时模拟耗时操作,显示等待光标QObject::connect(button, &QPushButton::clicked, [&]() {// 设置全局等待光标QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));// 模拟耗时任务(3秒后恢复光标)QTimer::singleShot(3000, []() {QApplication::restoreOverrideCursor();});});window.show();return app.exec();
}
动态切换光标(结合事件)
在某些场景下,需要根据用户交互动态切换光标样式,例如鼠标悬停或拖放操作。可以通过重写控件的事件处理函数(如 enterEvent、leaveEvent)或使用信号槽机制实现。
#include <QApplication>
#include <QWidget>
#include <QEvent>class CustomWidget : public QWidget {
protected:void enterEvent(QEvent *event) override {setCursor(QCursor(Qt::PointingHandCursor)); // 鼠标进入时设置为手形光标QWidget::enterEvent(event);}void leaveEvent(QEvent *event) override {unsetCursor(); // 鼠标离开时恢复默认光标QWidget::leaveEvent(event);}
};int main(int argc, char *argv[]) {QApplication app(argc, argv);CustomWidget widget;widget.resize(200, 200);widget.show();return app.exec();
}
2.3、自定义光标形状
2.3.1、使用 QPixmap 和 QBitmap 定义光标图像和掩码
可以通过 QPixmap 创建光标图像,并结合 QBitmap 定义光标的掩码(mask)来控制光标的透明区域和形状。
-
创建光标图像 (QPixmap):使用 QPixmap 加载或绘制光标图像。图像可以是 PNG、BMP 等格式,通常建议大小为 32x32 像素或更小,以符合系统光标大小限制。
-
创建光标掩码 (QBitmap):掩码是一个单色位图,用于指定光标的哪些部分是透明的(黑色表示透明,白色表示不透明)。
-
创建自定义光标 (QCursor):使用 QPixmap 和 QBitmap 创建 QCursor 对象。
-
应用光标:将光标应用到窗口或控件上:
-
注:如果 QPixmap 包含透明通道,掩码可以省略,直接使用 QCursor cursor(pixmap);。
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QBitmap>
#include <QPixmap>
#include <QPainter>int main(int argc, char *argv[]) {QApplication app(argc, argv);QWidget window;window.resize(300,400);QPixmap pixmap(":/images/save.png");//从 QPixmap 生成掩码QBitmap mask = pixmap.createMaskFromColor(Qt::transparent);// //手动绘制掩码:
// QBitmap mask(pixmap.size());
// QPainter painter(&mask);
// mask.fill(Qt::color0); // 黑色(透明)
// painter.setBrush(Qt::color1); // 白色(不透明)
// painter.drawEllipse(0, 0, 16, 16); // 绘制圆形不透明区域QCursor customCursor(pixmap, mask);// 创建自定义光标 (QCursor)window.setCursor(customCursor); // 设置到当前窗口window.show();return app.exec();
}
2.3.2、设置光标热点(Hotspot)
光标热点(Hotspot)是光标图像中表示点击位置的点(x, y 坐标)。例如,箭头光标的热点通常在其尖端,十字光标的热点在其中心。
指定热点坐标:
在创建 QCursor 时,通过参数指定热点的 x 和 y 坐标(相对于光标图像的左上角)。
QPixmap pixmap(":/cursor.png");
QCursor customCursor(pixmap, 16, 16); // 热点位于图像中心(假设图像为 32x32)
动态计算热点:
如果热点位置需要根据图像内容动态计算,可以分析图像的透明区域或关键点。例如,检测图像的最左侧不透明像素作为热点。
int hotX = pixmap.width() / 2;
int hotY = pixmap.height() / 2;
QCursor customCursor(pixmap, hotX, hotY);
注意:热点坐标必须在图像范围内(0 ≤ x < pixmap.width(), 0 ≤ y < pixmap.height()),否则可能导致光标行为异常。
2.3.3、动态或动画光标(通过定时器或事件循环更新)
动态或动画光标通过定时器或事件循环定期更新光标图像,实现光标的动态效果,例如旋转、闪烁或帧动画。
准备多帧图像:
创建一组 QPixmap 图像,用于表示动画的每一帧。例如,旋转光标可能包含 8 个不同角度的图像。
QList<QPixmap> frames;
frames << QPixmap(":/frame1.png") << QPixmap(":/frame2.png") << QPixmap(":/frame3.png");
使用定时器切换帧:
使用 QTimer 定期触发帧切换,更新光标。
class MyWidget : public QWidget {
public:MyWidget(QWidget *parent = nullptr) : QWidget(parent), currentFrame(0) {frames << QPixmap(":/frame1.png") << QPixmap(":/frame2.png") << QPixmap(":/frame3.png");QTimer *timer = new QTimer(this);connect(timer, &QTimer::timeout, this, &MyWidget::updateCursor);timer->start(100); // 每 100ms 更新一次}private:void updateCursor() {currentFrame = (currentFrame + 1) % frames.size(); // 循环切换帧QCursor cursor(frames[currentFrame]);setCursor(cursor);}QList<QPixmap> frames;int currentFrame;
};
2.4、光标的设置与管理
2.4.1、部件级别的光标设置 (QWidget::setCursor(), unsetCursor())
件级别的光标设置允许为特定的 QWidget(如窗口、按钮或自定义控件)设置自定义光标或系统预定义光标。QWidget 类提供了 setCursor() 和 unsetCursor() 方法来管理光标。
设置光标 (QWidget::setCursor()):
//设置系统箭头光标:
QWidget *widget = new QWidget;
widget->setCursor(Qt::ArrowCursor);//设置自定义光标(基于 QPixmap):
QPixmap pixmap(":/cursor.png");
QCursor customCursor(pixmap, 16, 16); // 热点坐标 (16, 16)
widget->setCursor(customCursor);
恢复默认光标 (QWidget::unsetCursor()):
调用 unsetCursor() 移除部件的自定义光标,恢复到父部件或应用程序的默认光标(通常是 Qt::ArrowCursor)。
widget->unsetCursor();
2.4.2、应用程序级别的全局光标设置 (QApplication::setOverrideCursor())
应用程序级别的光标设置允许临时覆盖整个应用程序的所有光标,通常用于表示全局状态(如等待或繁忙状态)。QApplication 类提供了 setOverrideCursor() 和 restoreOverrideCursor() 方法来实现这一功能。
设置全局光标 (QApplication::setOverrideCursor()):
//设置等待光标:
QApplication::setOverrideCursor(Qt::WaitCursor);//自定义光标
QPixmap pixmap(":/busy_cursor.png");
QCursor customCursor(pixmap, 16, 16);
QApplication::setOverrideCursor(customCursor);
恢复先前光标 (QApplication::restoreOverrideCursor()):
调用 restoreOverrideCursor() 移除当前全局光标,恢复之前的全局光标或部件级光标。
QApplication::restoreOverrideCursor();
光标栈管理:
setOverrideCursor() 支持光标栈,多次调用会将光标压栈,restoreOverrideCursor() 会弹出栈顶光标。
QApplication::setOverrideCursor(Qt::WaitCursor); // 压栈:等待光标
QApplication::setOverrideCursor(Qt::CrossCursor); // 压栈:十字光标
QApplication::restoreOverrideCursor(); // 弹出:恢复到等待光标
QApplication::restoreOverrideCursor(); // 弹出:恢复到默认光标
3、QIconEngine: 自定义图标渲染引擎
3.1、QIconEngine 简介
QIconEngine 是 Qt 中用于渲染 QIcon 对象的底层接口。QIcon 是一个高层次类,用于表示可在不同上下文(如按钮、工具栏、菜单等)中显示的图标,而 QIconEngine 负责实际的图标渲染逻辑。每个 QIcon 实例都关联一个 QIconEngine(或其子类),由 Qt 内部管理。
核心功能
-
图标渲染:根据请求的大小、模式(如正常、禁用、选中)和状态(如激活、悬停)生成图标图像。
-
多分辨率支持:提供不同尺寸或像素密度的图标,适配高 DPI 显示。
-
动态生成:支持运行时生成图标,而非依赖静态图像文件。
内置的 QIconEngine
-
QPixmapIconEngine:基于 QPixmap 的静态图像渲染。
-
QImageIconEngine:基于 QImage 的渲染。
-
QSvgIconEngine:用于 SVG 矢量图标的渲染。
3.2、QIconEngine 的工作原理
QIconEngine 是一个抽象基类,开发者需要实现其核心虚函数以定义图标的渲染逻辑。
3.2.1、抽象基类及其核心虚函数
QIconEngine 定义在 <QIconEngine> 头文件中。
virtual void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) = 0
-
painter:用于绘制的画笔。
-
rect:目标矩形区域,定义图标的绘制大小和位置。
-
mode:图标模式(QIcon::Normal、QIcon::Disabled、 QIcon::Active、QIcon::Selected)。
-
state:图标状态(QIcon::On 或 QIcon::Off,例如复选框的选中/未选中状态)。
virtual QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
-
返回指定大小、模式和状态的图标图像(QPixmap)。
-
默认实现通过调用 paint() 渲染到 QPixmap,通常无需重写。
-
参数同 paint(),但以 QSize 指定尺寸。
virtual QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state)
-
返回图标的实际大小,可能受限于图标的固有尺寸。
-
默认实现返回请求的 size,可重写以支持特定约束。
virtual QIconEngine *clone() const:
-
创建引擎的副本,用于 QIcon 的复制操作。
-
必须实现,通常返回一个新的引擎实例。
virtual QString key() const:
-
返回引擎的唯一标识符,用于缓存或比较。
-
默认实现返回类名,可重写以提供更具体的值。
virtual void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state):
-
添加静态 QPixmap 作为图标内容(可选)。
-
常用于混合静态和动态渲染。
virtual void addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state):
-
从文件加载图标(可选)。
-
常用于支持文件路径的图标加载。
virtual QStringList availableSizes(QIcon::Mode mode, QIcon::State state) const:
-
返回支持的图标尺寸(可选)。
-
用于多分辨率图标支持。
3.2.2、paint() 方法的实现(核心渲染逻辑)
paint() 是 QIconEngine 的核心方法,负责实际的图标绘制。
初始化画笔:配置 QPainter 的属性(如抗锯齿、画刷、笔)以确保高质量渲染。
处理模式和状态:根据 state 切换图标内容(例如开关的开/关状态)。根据 mode 调整渲染效果:
-
QIcon::Normal:标准渲染。
-
QIcon::Disabled:降低透明度或使用灰度。
-
QIcon::Active:高亮或加粗。
-
QIcon::Selected:更改颜色或背景。
绘制图标:使用 QPainter 绘制形状、路径或图像,适配目标 rect。
适配大小:确保绘制内容填充 rect,必要时缩放或裁剪。
3.2.3、pixmap() 方法的实现(获取缓存图像)
pixmap() 方法用于生成指定大小、模式和状态的 QPixmap,通常由 Qt 内部调用以缓存渲染结果。默认实现通过调用 paint() 完成渲染,开发者可以选择重写以优化性能。
默认实现
默认的 pixmap() 方法创建一个 QPixmap,调用 paint() 绘制内容:
QPixmap QIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) {QPixmap pixmap(size);pixmap.fill(Qt::transparent);QPainter painter(&pixmap);paint(&painter, QRect(QPoint(0, 0), size), mode, state);return pixmap;
}
自定义实现
如果需要优化(如缓存特定尺寸的图像),可以重写 pixmap():使用 QCache 或 QMap 存储已渲染的 QPixmap,避免重复渲染。
3.2.4、示例代码
展示动态圆形图标的渲染,支持不同模式和状态,并使用缓存优化 pixmap():
#include <QApplication>
#include <QPushButton>
#include <QIconEngine>
#include <QPainter>
#include <QCache>class CircleIconEngine : public QIconEngine {
public:CircleIconEngine() = default;QIconEngine *clone() const override { return new CircleIconEngine(); }void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override {painter->setRenderHint(QPainter::Antialiasing, true);// 根据模式和状态调整颜色QColor color = (mode == QIcon::Disabled) ? Qt::gray :(mode == QIcon::Selected) ? Qt::blue :(mode == QIcon::Active) ? Qt::green : Qt::red;if (mode == QIcon::Disabled) {painter->setOpacity(0.5);}// 根据状态调整形状if (state == QIcon::On) {painter->setBrush(color);painter->drawEllipse(rect); // 实心圆} else {painter->setPen(QPen(color, 2));painter->setBrush(Qt::NoBrush);painter->drawEllipse(rect); // 空心圆}}QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override {QString cacheKey = QString("%1_%2_%3_%4").arg(size.width()).arg(size.height()).arg(mode).arg(state);if (cache.contains(cacheKey)) {return *cache.object(cacheKey);}QPixmap pixmap(size);pixmap.fill(Qt::transparent);QPainter painter(&pixmap);paint(&painter, QRect(QPoint(0, 0), size), mode, state);cache.insert(cacheKey, new QPixmap(pixmap));return pixmap;}private:static QCache<QString, QPixmap> cache;
};QCache<QString, QPixmap> CircleIconEngine::cache(100);int main(int argc, char *argv[]) {QApplication app(argc, argv);// 创建 QIcon 使用自定义引擎QIcon icon(new CircleIconEngine());// 创建按钮并设置图标QPushButton button;button.setIcon(icon);button.setIconSize(QSize(64, 64));button.setText("Dynamic Icon");button.setCheckable(true); // 支持 On/Off 状态button.resize(200, 100);button.show();return app.exec();
}
3.3、实现自定义图标引擎
3.3.1、子类化 QIconEngine
要创建自定义图标引擎,需要继承 QIconEngine 并实现其核心虚函数,尤其是 paint() 和 clone()。
-
继承 QIconEngine:创建一个新类,继承自 QIconEngine
-
实现核心虚函数:
-
paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state):定义图标的绘制逻辑。
-
clone() const:返回引擎的副本,用于 QIcon 复制。
-
可选实现 pixmap()、actualSize() 等函数以优化性能或支持特定功能。
-
-
添加自定义逻辑:根据需求添加成员变量或构造函数,用于存储图标的参数(如形状、颜色)。
#include <QIconEngine>
#include <QPainter>class CustomIconEngine : public QIconEngine {
public:CustomIconEngine() = default;QIconEngine *clone() const override {return new CustomIconEngine(*this);}void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override {painter->setRenderHint(QPainter::Antialiasing, true);painter->setBrush(Qt::red);painter->drawEllipse(rect); // 示例:绘制红色圆形}
};
3.3.2、集成第三方 SVG 渲染库或字体图标库
假设使用 Font Awesome 字体,需先将字体文件(如 fa-solid-900.ttf)加载到应用中。确保字体文件已经拷贝到执行目录下:
#include <QApplication>
#include <QPushButton>
#include <QIconEngine>
#include <QPainter>
#include <QCache>#include <QPainter>
#include <QFontDatabase>
#include <QFont>class FontIconEngine : public QIconEngine {
public:FontIconEngine(const QString &iconCode, const QColor &color, qreal size): iconCode_(iconCode), color_(color), size_(size) {// 加载字体QFontDatabase db;int fontId = db.addApplicationFont("fa-solid-900.ttf");fontFamily_ = db.applicationFontFamilies(fontId).first();}QIconEngine *clone() const override {return new FontIconEngine(iconCode_, color_, size_);}void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override {painter->setRenderHint(QPainter::Antialiasing, true);// 设置字体QFont font(fontFamily_);font.setPixelSize(qMin(rect.width(), rect.height()) * 0.8);painter->setFont(font);// 根据模式调整颜色QColor renderColor = color_;if (mode == QIcon::Disabled) {renderColor = renderColor.lighter(150);painter->setOpacity(0.5);} else if (mode == QIcon::Selected) {renderColor = Qt::blue;}painter->setPen(renderColor);// 居中绘制图标painter->drawText(rect, Qt::AlignCenter, iconCode_);}private:QString iconCode_; // 字体图标的 Unicode 码点(如 "\uf015" 表示家图标)QColor color_;qreal size_;QString fontFamily_;
};int main(int argc, char *argv[]) {QApplication app(argc, argv);// 创建 Font Awesome 家图标,QIcon homeIcon(new FontIconEngine(QString(QChar(0xf015)), Qt::black, 32));// 创建按钮并设置图标QPushButton button;button.setIcon(homeIcon);button.setIconSize(QSize(64, 64));button.setText("Home Icon");button.resize(200, 100);button.show();return app.exec();
}
效果:
3.4、将自定义引擎与 QIcon 关联使用
创建引擎实例:实例化自定义的 QIconEngine 子类。
DynamicIconEngine *engine = new DynamicIconEngine(DynamicIconEngine::Circle, Qt::red);
创建 QIcon:使用 QIcon(QIconEngine *engine) 构造函数,将引擎传递给 QIcon。
QIcon icon(engine);
应用到控件:将 QIcon 设置到按钮、工具栏或其他支持图标的控件上。
QPushButton button;
button.setIcon(icon);
button.setIconSize(QSize(64, 64));
九. 平台和渲染后端
提供平台特定集成和渲染后端支持。
-
QPlatformIntegration: 平台特定的窗口系统集成(Windows、X11、Wayland 等)。
-
QRasterPaintEngine: 软件光栅化渲染引擎。
-
QPlatformSurface: 平台特定的渲染表面。
-
QPlatformTheme: 平台主题(如按钮样式、对话框风格)。
-
QPlatformGraphicsBuffer: 平台特定的图形缓冲区。
-
QPlatformSharedGraphicsCache: 共享图形缓存,加速渲染。
十. 国际化(GUI 相关)
支持 GUI 相关的字符编码和区域设置。
-
QTextCodec(部分):字符编码支持(仅限 GUI 文本显示)。
-
QLocale(部分):区域设置(仅限 GUI 格式,如日期、数字显示)。
相关文章:
QtGUI模块功能详细说明,图标和光标(七)
目录 一.窗口和屏幕管理 二. 绘图和渲染 三. 图像处理 四. 字体和文本 五. 事件和输入处理 六. OpenGL 和硬件加速 七. 颜色和外观 八. 图标和光标 1、QIcon: 图标管理 1.1、QIcon 简介 1.2、图标的来源与创建 1.3、多分辨率与 DPI 支持 1.4、图标的状态管理 2、…...
【图像处理基石】如何入门OCR技术?
入门OCR(Optical Character Recognition,光学字符识别)技术需要结合理论学习、工具实践和项目实战,以下是分步骤的学习指南,适合零基础学习者: 一、明确OCR技术的核心概念 OCR的基本原理 核心流程…...
数据库知识沉浸式游戏化学习设计研究
数据库知识沉浸式游戏化学习设计研究 摘要: 本研究旨在设计一款以数据库知识为主题的沉浸式游戏化学习系统。通过对数据库知识体系的深入剖析,结合游戏化学习理论,构建了一个多层次、多任务的游戏架构。玩家在游戏过程中需完成构建数据库结构、编写 SQL 查询等任务来解锁关…...
大疆无人机
在大疆上云API中,DRC 链路通常指 Device-Cloud Remote Control Link(设备-云端远程控制链路),它是无人机(或设备)与云端服务之间建立的实时控制与数据传输通道,用于实现…...
撤回不了一点 v1.0.2,支持微信QQ钉钉飞书等消息防撤回
如今生活节奏快得飞起,社交软件和工作通讯软件成了咱日常交流的核心阵地。大家肯定都有过这些闹心事儿:和朋友聊得正嗨,对方突然撤回一条消息,好奇心瞬间爆棚,却怎么也看不到撤回的内容;工作群里关键信息刚…...
什么是Git?
“Git”是目前非常火、广泛使用的版本控制系统,尤其在软件开发领域中扮演着核心角色。 一、什么是Git?它到底是什么? Git 是一种版本控制系统(Version Control System, VCS)。它的主要作用是帮助开发者管理“代码的不…...
微信小程序 自定义图片分享-绘制数据图片以及信息文字
一 、需求 从数据库中读取头像,姓名电话等信息,当分享给女朋友时,每个信息不一样 二、实现方案 1、先将数据库中需要的头像姓名信息读取出来加载到data 数据项中 data:{firstName:, // 姓名img:, // 头像shareImage:,// 存储临时图片 } 2…...
langchain提示词的使用
一、概述 提示词是指向人工智能大模型提供的输入信息,通常包含关键词、问题或指令,可以引导大模型生成与用户期望相符的回应。我们在豆包,DeepSeek等大模型中输入的问题都可以认为一个简单的提示词,不过为了真正得到我们需要的结…...
C语言| extern的用法作用
C语言| 局部变量、全局变量 extern定义的变量,只对全局变量有用。 掌握extern的用法及其作用。extern主要用于在不同.c文件间扩展全局变量的作用范围。 扩展全局变量的使用范围,操作方法: 1 在一个文件内扩展全局变量的使用范围 全局变量…...
Rust 环境变量管理秘籍:从菜鸟到老鸟都爱的 dotenv 教程
前言 写代码的你,是否遭遇过这些灵魂拷问: “我现在在哪个环境?开发?测试?还是直接在生产线上裸奔?”“少写一个 .env,测试脚本在数据库里上演清空大法,客户当场破防。”“每次手动设置 RUST_ENV,命令敲到一半就开始怀疑人生,还怕输错一个字符引发灭世级事故。”别慌…...
Leetcode (力扣)做题记录 hot100(49,136,169,20)
力扣第49题:字母异位词分组 49. 字母异位词分组 - 力扣(LeetCode) 遍历数组,将每一个字符串变成char数组 然后排序,如果map里面有则将他的值返回来(key是排序好的字符串) class Solution {pu…...
Slitaz 系统深度解析
Slitaz 系统深度解析:从系统架构到设计哲学 一、系统定位与核心目标 Slitaz(Simplified Lightweight IT Automatic Zen)是一个基于 Linux 的超轻量级发行版,设计目标是极致轻量化、快速启动、低资源消耗,专为老旧硬件…...
Deepseek+Xmind:秒速生成思维导图与流程图
deepseekxmind,快速生成思维导图和流程图 文章目录 思维导图deepseek笔记本 txt文件xmind 流程图deepseekdraw.io 思维导图 deepseek 笔记本 txt文件 将deep seek的东西复制到文本文件中,然后将txt文件拓展名改成md xmind 新建思维导图----左上角三…...
理解计算机系统_并发编程(5)_基于线程的并发(二):线程api和基于线程的并发服务器
前言 以<深入理解计算机系统>(以下称“本书”)内容为基础,对程序的整个过程进行梳理。本书内容对整个计算机系统做了系统性导引,每部分内容都是单独的一门课.学习深度根据自己需要来定 引入 接续上一篇理解计算机系统_并发编程(4)_基于线程的并发(一…...
java刷题基础知识
List<int[]> merged new ArrayList<int[]>(); return merged.toArray(new int[merged.size()][]); 表示一个存储 int[] 类型元素的列表,list灵活支持扩展,因为不知道最后有几个区间,所以用list,最后toArray返回成数组…...
MATLAB语音情感识别神经网络方法
在MATLAB中使用神经网络进行语音情感识别通常涉及以下步骤:数据准备、特征提取、神经网络模型构建、训练与评估。以下是详细说明和示例代码: 1. 数据准备 数据集:推荐使用公开情感语音数据集(如RAVDESS、CREMA-D、EMODB等&#x…...
PostgreSQL 服务器信号函数
PostgreSQL 服务器信号函数 PostgreSQL 提供了一组服务器信号函数(Server Signaling Functions),允许数据库管理员向 PostgreSQL 服务器进程发送特定信号以控制服务器行为。这些函数提供了对数据库服务器的精细控制能力。 一、核心信号函数…...
流动式起重机Q2的培训内容有哪些?
流动式起重机 Q2 的培训内容主要分为理论知识和实际操作两部分,具体如下: 理论知识 基础理论知识:涵盖机械原理、液压原理、电气原理等内容,帮助学员理解起重机的基本工作原理。例如,通过机械原理知识,学员…...
虹科应用 | 探索PCAN卡与医疗机器人的革命性结合
随着医疗技术的不断进步,医疗机器人在提高手术精度、减少感染风险以及提升患者护理质量方面发挥着越来越重要的作用。医疗机器人的精确操作依赖于稳定且高效的数据通信系统,虹科提供的PCAN四通道mini PCIe转CAN FD卡,正是为了满足这一需求而设…...
Linux系统编程---Signal信号集
0、前言 在上一篇博客笔记文章中,对Linux进程间通信的信号进行了讲解,本章将接着上一篇文章的内容,继续对Linux进程间通信中信号部分的信号集这个小知识点进行梳理。 如果有对Linux系统编程有不了解的地方,欢迎查阅博主的Linux系统…...
上电单次复位触发电路
SA1相当于是另外一个触发信号,S2A是手动触发信号,当S1A和S2A开关都断开时,示波器A入口所连接线路为上拉状态,高电平为3V。 当S2A闭合,相当于手动拉低,可以用于唤醒单片机之类的。 当S1A闭合,模拟电源接入&…...
talk-linux 不同用户之间终端通信
好的!下面是一个完整的指南和脚本,用于在两台 Linux 主机上配置并使用 talk 聊天功能(假设它们在同一个局域网内)。 ⸻ 🧾 一、需求说明 我们需要在两台主机上: 1. 安装 talk 和 talkd 2. 启用 talkd 服…...
QGIS 将 Shapefile 导入 PostGIS 数据库
一、背景介绍:QGIS、PostgreSQL 和 PostGIS 的关系和用途 在开始动手操作之前,我们先简单了解一下 QGIS、PostgreSQL 和 PostGIS 之间的关系及其用途。 QGIS(Quantum GIS):一款开源免费的桌面地理信息系统࿰…...
《内网渗透测试:绕过最新防火墙策略》
内网渗透测试是检验企业网络安全防御体系有效性的核心手段,而现代防火墙策略的持续演进(如零信任架构、AI流量分析、深度包检测)对攻击者提出了更高挑战。本文系统解析2024年新型防火墙的防护机制,聚焦协议隐蔽隧道、上下文感知绕…...
CSS结构性伪类、UI伪类与动态伪类全解析:从文档结构到交互状态的精准选择
一、结构性伪类选择器:文档树中的位置导航器 结构性伪类选择器是CSS中基于元素在HTML文档树中的层级关系、位置索引或结构特征进行匹配的一类选择器。它们无需依赖具体的类名或ID,仅通过文档结构即可精准定位元素,是实现响应式布局和复杂文档…...
【大模型LLM学习】MiniCPM的注意力机制学习
【大模型LLM学习】MiniCPM的注意力机制学习 前言1 Preliminary1.1 MHA1.2 KV-cache 2 GQAGQA的MiniCPM实现 3 MLAMLA的MiniCPM-3-4b的实现 TODO 前言 之前MiniCPM3-4B是最早达到gpt-3.5能力的端侧小模型,其注意力机制使用了MLA。本来想借着MiniCPM从MHA过到MLA的&am…...
stm32之PWR、WDG
目录 1.PWR1.1 简介1.2 电源框图1.3 上电复位和掉电复位1.4 可编程电压监测器1.5 低功耗模式1.5.1 模式选择1.5.2 睡眠模式1.5.3 停止模式1.5.4 待机模式 1.6 实验1.6.1 修改主频1.6.2 睡眠模式串口发送接收1.6.3 停止模式对射式红外传感器计次1.6.4 待机模式实时时钟 2.看门狗…...
分布式任务调度XXL-Job
XXL-Job 是一款轻量级、分布式的任务调度平台,其核心设计解决了传统任务调度(如Quartz)在分布式场景下的任务分片、高可用、可视化管控等痛点。以下从原理、核心架构、应用场景、代码示例及关联中间件展开详解 一、主流任务…...
内存泄漏与OOM崩溃根治方案:JVM与原生内存池差异化排查手册
内存泄漏与OOM崩溃根治方案:JVM与原生内存池差异化排查手册 一、问题描述与快速解决方案 1. 核心问题分类 内存泄漏(Memory Leak) 现象:应用运行时间越长,内存占用持续攀升,GC回收效率下降,最…...
火山引擎发展初始
火山引擎是字节跳动旗下的云计算服务品牌,其云服务业务的启动和正式商业化时间线如下: 1. **初期探索(2020年之前)** 字节跳动在早期为支持自身业务(如抖音、今日头条等)构建了强大的基础设施和技术中…...
使用光标测量,使用 TDR 测量 pH 和 fF
时域反射计 (TDR) 是一种通常用于测量印刷电路板 (PCB) 测试试样和电缆阻抗的仪器。TDR 对于测量过孔和元件焊盘的电感和电容、探针尖端电容和电感,甚至寄生电感收发器耦合电容器也非常有用。这也是验证仿真或提取您自…...
mybatisplus 集成逻辑删除
一开始,没去查资料,后面要被AI气死了,先看它的的话 一开始,看ai的描述,我还以为,不需要改数据库,mybatis-puls自动拦截集成就可以实现逻辑删除,c,最后还是要给数据库加一…...
ABAP+旧数据接管的会计年度未确定
导资产主数据时,报错旧数据接管的会计年度未确定 是因为程序里面使用了下列函数AISCO_CALCULATE_FIRST_DAY,输入公司代码,获取会计年度,这个数据是在后台表T093C表中取数的,通过SE16N可以看到后台表数据没有数…...
KT148A语音芯片发码很难播放_将4脚对地一下再发正常,什么原因?
问题描述如下:您好,遇到一点问题请帮忙支持一下: KT148A 这颗芯片, 我们上电后发码很难触发播放, 但用镊子将4pin PB0对地短接触发一下,再发码就很正常,这是什么原因? 根据现象来看…...
【大模型】DeepResearcher:通用智能体通过强化学习探索优化
DeepResearcher:通过强化学习在真实环境中扩展深度研究 一、引言二、技术原理(一)强化学习与深度研究代理(二)认知行为的出现(三)模型架构 三、实战运行方式(一)环境搭建…...
SpringBoot 3.X 开发自己的 Spring Boot Starter 和 SpringBoot 2.x 的区别
SpringBoot 2.x 在模块中创建 src/main/resources/META-INF/spring.factories 文件 文件内容如下: org.springframework.boot.autoconfigure.EnableAutoConfiguration\com.xxx.xxx.yourfilejava1,\com.xxx.xxx.yourfilejava2 SpringBoot 3.x 在模块中创建 src/m…...
NY164NY165美光固态闪存NY166NY172
美光NY系列固态闪存深度解析:技术、体验与行业洞察 一、技术架构与核心特性解析 美光NY系列(NY164/NY165/NY166/NY172)作为面向企业级市场的固态闪存产品,其技术设计聚焦高可靠性与性能优化。从架构上看,该系列可能采…...
Spring Boot中HTTP连接池的配置与优化实践
精心整理了最新的面试资料和简历模板,有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 一、HTTP连接池的核心价值 在微服务架构和分布式系统场景中,HTTP客户端频繁创建/断开连接会产生显著的性能损耗。通过连接池技术可以实现&#x…...
【docker】--镜像管理
文章目录 拉取镜像启动镜像为容器连接容器法一法二 保存镜像加载镜像镜像打标签移除镜像 拉取镜像 docker pull mysql:8.0.42启动镜像为容器 docker run -dp 8080:8080 --name container_mysql8.0.42 -e MYSQL_ROOT_PASSWORD123123123 mysql:8.0.42 连接容器 法一 docker e…...
Logisim实验--华科计算机组成原理(保姆级教程) 头歌-存储系统设计实验(汉字库存储芯片扩展实验、MIPS寄存器文件设计)
汉字库存储芯片扩展实验 电路一: 电路二:电路和译码器设置。 两个电路的分线器设计: 只要把电路正确连接就能提交了,但要看到正确的实验结果就想要进行如下操作: 打开参考电路,我要做的就是将每个存储器内…...
Hapi.js知识框架
一、Hapi.js 基础 1. 核心概念 企业级Node.js框架:由Walmart团队创建,现由社区维护 配置驱动:强调声明式配置而非中间件 插件架构:高度模块化设计 安全优先:内置安全最佳实践 丰富的生态系统:官方维护…...
Baklib知识中台架构与智能引擎实践
知识中台架构设计实践 在数字化转型进程中,Baklib基于企业级知识管理需求,构建了模块化分层架构的知识中台体系。该架构采用数据湖仓融合技术,通过统一元数据管理打通业务系统间的信息壁垒,形成覆盖数据采集、清洗、标注的全链路…...
传输层协议UDP
传输层 负责数据能够从发送端传输接收端 . 再谈端口号 端口号 (Port) 标识了一个主机上进行通信的不同的应用程序 ; 在 TCP/IP 协议中 , 用 " 源 IP", " 源端口号 ", " 目的 IP", " 目的端口号 ", " 协议号 " 这样一…...
在Java中实现Parcelable接口和Serializable接口有什么区别?
在 Java 中,Parcelable 和 Serializable 接口都用于对象的序列化和反序列化,但它们的实现方式、性能和使用场景有很大区别。以下是它们的核心对比: 1. 实现方式 Serializable 是 Java 原生接口,只需声明 implements Serializable…...
MinIO WebUI 页面使用
上传文件到桶,选择Share 如果桶是pulic权限,则可以有以下两种方式访问到该对象文件: http://ip:9001/api/v1/download-shared-object/aHR0cDovLzEyNy4wLjAuMTo5MDAwL3dhcmVob3VzZS9wYWltb24vRmxpbmstTG9nby5wbmc_WC1BbXotQWxnb3JpdGhtPUFXU…...
Python | Dashboard制作
运行环境:jupyter notebook (python 3.12.7) Pyecharts 1.安装pyecharts !pip install pyecharts 验证安装是否成功: from pyecharts import __version__ print("Pyecharts版本:", __version__) # 应显示1.x以上版本 2.运行基础版代码&am…...
视频编辑软件无限音频、视频、图文轨
威力导演APP的特色功能包括无限音频、视频、图文轨,以及上百种二/三维特技转场、音/视频滤镜和多种音视频混编输出。此外,它还支持实时高清HDV格式、模拟信号输出,并具有DV25、DVACM、DV、HDV输入和输出等功能。在视频编辑领域,威…...
HttpSession 的运行原理
HttpSession 的运行原理(基于 Java Web) HttpSession 是 Java Web 开发中用于在服务器端存储用户会话数据的机制,它的核心作用是跟踪用户状态(如登录信息、购物车数据等)。 1. HttpSession 的基本概念 会话࿰…...
Axure应用交互设计:表格跟随菜单移动效果(超长表单)
亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢!本文如有帮助请订阅 Axure产品经理精品视频课已登录CSDN可点击学习https://edu.csdn.net/course/detail/40420 课程主题:表格跟随菜单移动 主要内容:表格交互设计、动态面板嵌套、拖动时事件、移动动作 应用场景…...
Flannel vxlan模式的优缺点
VXLAN 模式的特点、优缺点 优点 高性能:VXLAN 利用内核态处理封装/解封装,性能优于用户态方案(如 UDP),适合大规模集群。网络隔离:通过 VNI(VXLAN Network Identifier,24 位&#…...