基于 Qt 5.14.2 / C++11 的图片标尺查看器,支持自适应缩放、拖拽平移、ROI 裁剪。
RulerImageWidget/
├── main.cpp # 程序入口,主窗口布局与信号槽连接
├── rulerimagewidget.h # 核心控件头文件
├── rulerimagewidget.cpp # 核心控件实现(标尺绘制、交互、裁剪)
├── RulerImageWidget.pro # Qt 工程文件
└── res/images/
├── images.qrc # Qt 资源文件(前缀 /pictures)
├── 1.jpg # 默认加载图片
| 功能 | 说明 |
|---|---|
| 图片加载 | 支持从本地文件系统加载图片,也支持从 Qt 资源文件加载 |
| 自适应居中 | 图片加载后自动计算缩放比例,居中显示在标尺区域内 |
| 横轴 / 纵轴标尺 | 根据当前缩放比例动态绘制像素坐标刻度,支持无限缩放 |
| 鼠标缩放 | 滚轮以鼠标位置为中心进行缩放 |
| 拖拽平移 | 左键或右键拖拽平移图片,标尺同步更新 |
| ROI 框选 | 进入 ROI 模式后,左键拖拽绘制蓝色半透明选区,实时显示原始像素尺寸 |
| ROI 裁剪 | 根据选区从原图裁剪并保存为 PNG / JPG / BMP |
整个控件通过重写 paintEvent 完成所有绘制,绘制顺序:
- 图片绘制 —
translate(offset)→scale(s)→drawImage(0, 0, img),通过QPainter::save/restore隔离变换状态 - 标尺覆盖层 — 在图片上方绘制半透明标尺背景和刻度
- ROI 选区 — 蓝色半透明矩形 + 尺寸文字标注
开启了 QPainter::Antialiasing 和 QPainter::SmoothPixmapTransform 保证渲染质量。
标尺刻度根据缩放比例自适应调整步长,核心流程:
目标像素间距 (50px) / 当前缩放比例 = 理想单位间距
↓
取 log10 找到最近的 10 的幂次基准 (1, 10, 100...)
↓
按 1-2-5 进制细化 (1→2→5→10→20→50→100...)
↓
步长 × 缩放比例 = 屏幕像素间距
每个主刻度区间等分为 5 个次级刻度,标注显示原始图像坐标值。
存在三个坐标系之间的转换:
| 坐标系 | 说明 |
|---|---|
| 控件坐标 | 鼠标事件 event->pos() 返回的屏幕像素坐标 |
| 画布坐标 | 经过 offset 和 scale 变换后的中间坐标 |
| 图像坐标 | 原始图片的像素坐标(ROI 裁剪使用) |
转换公式:
图像坐标 = (控件坐标 - imageOffset) / scale
画布坐标 = 图像坐标 × scale + imageOffset
| 事件 | 普通模式 | ROI 模式 |
|---|---|---|
| 左键按下 | 开始拖拽平移 | 开始框选 |
| 左键移动 | 平移图片 | 绘制选区矩形 |
| 左键释放 | 结束平移 | 计算 ROI 图像坐标,发射 roiChanged 信号 |
| 右键按下/移动/释放 | 平移图片 | 平移图片 |
| 滚轮 | 以鼠标为中心缩放 | 以鼠标为中心缩放 |
// 控件发射信号
void RulerImageWidget::roiChanged(); // ROI 选区完成时
// main.cpp 中连接
connect(rulerWidget, &RulerImageWidget::roiChanged, [=]() {
btnCrop->setEnabled(true);
});按钮栏通过 Lambda 表达式直接捕获局部变量连接信号,无需定义额外的槽函数。
- 使用
QImageReader加载图片,开启setAutoTransform(true)自动处理 EXIF 旋转信息 - 自适应算法:取
min(viewWidth/imgWidth, viewHeight/imgHeight) × 0.9作为缩放比例,留 10% 边距 resizeEvent中自动重新计算,窗口缩放时图片始终保持居中
- 选区以
QRectF存储为原始图像坐标 - 裁剪时通过
QRectF::intersected()限制在原图范围内 - 使用
QImage::copy()提取子区域,支持保存为多种格式
使用 Qt Creator 打开 RulerImageWidget.pro,选择 Kit 后直接构建运行。
# 或命令行编译
qmake RulerImageWidget.pro
make # Linux/macOS
nmake # Windows MSVC
mingw32-make # Windows MinGW- Qt 5.14.2+
- C++11
- 模块:
core、gui、widgets