qt-C++笔记之QLine、QRect、QPainterPath、和自定义QGraphicsPathItem、QGraphicsRectItem的区别
code review!
参考笔记
1.qt-C++笔记之重写QGraphicsItem的paint方法(自定义QGraphicsItem)
文章目录
- qt-C++笔记之QLine、QRect、QPainterPath、和自定义QGraphicsPathItem、QGraphicsRectItem的区别
- 一、QLine、QPainterPath、QGraphicsPathItem、自定义 QGraphicsPathItem 的区别与使用场景
- 表格:类的比较
- 简洁对比示例
- 示例 1:使用 QLine 绘制简单直线
- 示例 2:使用 QPainterPath 绘制复杂路径
- 示例 3:在 QGraphicsScene 中使用 QGraphicsPathItem
- 示例 4:自定义 QGraphicsPathItem 并实现特殊交互
- 二、QRect、QGraphicsRectItem、自定义 QGraphicsRectItem 的区别与使用场景
- 表格:类的比较
- 简洁对比示例
- 示例 1:使用 QRect 进行布局计算
- 示例 2:在 QGraphicsScene 中使用 QGraphicsRectItem
- 示例 3:自定义 QGraphicsRectItem 并实现特殊功能
- 三、总结比较
- 表格:关键区别和适用场景
- 四、自定义 QGraphicsRectItem、自定义 QGraphicsPathItem 与自定义 QGraphicsItem 的区别
- 4.1 继承层次与基础功能
- 4.2 差异对比
- 五、使用场景与示例
- 5.1 自定义 QGraphicsRectItem
- 5.2 自定义 QGraphicsPathItem
- 5.3 自定义 QGraphicsItem
- 六、总结与选择建议
- 6.1 何时选择自定义 QGraphicsRectItem / QGraphicsPathItem
- 6.2 何时选择自定义 QGraphicsItem
- 6.3 选择建议
一、QLine、QPainterPath、QGraphicsPathItem、自定义 QGraphicsPathItem 的区别与使用场景
表格:类的比较
类名 | 定义 | 特点 | 使用场景 |
---|---|---|---|
QLine | 表示由两点定义的直线段 | - 轻量级 - 整数精度 | - 几何计算 - 基本绘制 |
QPainterPath | 描述复杂绘图路径的类 | - 灵活构建任意复杂路径 - 浮点精度 - 支持布尔运算 | - 复杂形状绘制 - 路径动画 |
QGraphicsPathItem | 在 QGraphicsScene 中显示 QPainterPath 的图形项 | - 可视化复杂路径 - 支持交互和变换 | - 图形编辑器 - 数据可视化 |
自定义 QGraphicsPathItem | 继承 QGraphicsPathItem,实现自定义行为 | - 可扩展性强 - 重写事件处理和绘制方法 | - 定制交互 - 特定功能组件 |
简洁对比示例
示例 1:使用 QLine 绘制简单直线
QLine line(0, 0, 100, 100);
QPainter painter(this);
painter.drawLine(line);
- 使用场景:当需要在窗口上绘制简单的直线时。
示例 2:使用 QPainterPath 绘制复杂路径
QPainterPath path;
path.moveTo(0, 0);
path.lineTo(50, 100);
path.cubicTo(80, 0, 120, 100, 150, 0);
QPainter painter(this);
painter.drawPath(path);
- 使用场景:当需要绘制复杂的曲线和形状时。
示例 3:在 QGraphicsScene 中使用 QGraphicsPathItem
QPainterPath path;
path.addEllipse(0, 0, 100, 100);
QGraphicsScene *scene = new QGraphicsScene(this);
QGraphicsView *view = new QGraphicsView(scene, this);
QGraphicsPathItem *item = new QGraphicsPathItem(path);
scene->addItem(item);
- 使用场景:当需要将复杂路径添加到场景中以支持交互时。
示例 4:自定义 QGraphicsPathItem 并实现特殊交互
class MyPathItem : public QGraphicsPathItem {
public:
MyPathItem(const QPainterPath &path) : QGraphicsPathItem(path) {}
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override {
// 实现自定义的鼠标按下事件处理
}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override {
// 实现自定义的绘制
QGraphicsPathItem::paint(painter, option, widget);
}
};
// 使用自定义项
QPainterPath path;
// ... 构建路径 ...
MyPathItem *item = new MyPathItem(path);
scene->addItem(item);
- 使用场景:当需要自定义图形项的交互行为或绘制外观时。
二、QRect、QGraphicsRectItem、自定义 QGraphicsRectItem 的区别与使用场景
表格:类的比较
类名 | 定义 | 特点 | 使用场景 |
---|---|---|---|
QRect | 表示矩形区域的类 | - 轻量级 - 整数精度 | - 布局计算 - 区域检测 |
QGraphicsRectItem | 在 QGraphicsScene 中显示矩形的图形项 | - 可视化矩形 - 支持交互和变换 | - 图形元素 - 绘图工具 |
自定义 QGraphicsRectItem | 继承 QGraphicsRectItem,实现自定义行为 | - 可扩展性强 - 重写事件处理和绘制方法 | - 特定交互 - 组件封装 |
简洁对比示例
示例 1:使用 QRect 进行布局计算
QRect rect(0, 0, 100, 50);
QPoint point(50, 25);
if (rect.contains(point)) {
// 点在矩形内
}
- 使用场景:用于界面元素的位置和布局计算。
示例 2:在 QGraphicsScene 中使用 QGraphicsRectItem
QGraphicsScene *scene = new QGraphicsScene(this);
QGraphicsView *view = new QGraphicsView(scene, this);
QGraphicsRectItem *item = new QGraphicsRectItem(0, 0, 100, 50);
item->setBrush(Qt::blue);
scene->addItem(item);
- 使用场景:当需要在场景中显示矩形并支持交互时。
示例 3:自定义 QGraphicsRectItem 并实现特殊功能
class MyRectItem : public QGraphicsRectItem {
public:
MyRectItem(qreal x, qreal y, qreal w, qreal h) : QGraphicsRectItem(x, y, w, h) {}
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override {
// 实现自定义的鼠标按下事件处理
}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override {
// 实现自定义的绘制,例如绘制渐变填充
QLinearGradient gradient(rect().topLeft(), rect().bottomRight());
gradient.setColorAt(0, Qt::white);
gradient.setColorAt(1, Qt::blue);
painter->setBrush(gradient);
painter->drawRect(rect());
}
};
// 使用自定义项
MyRectItem *item = new MyRectItem(0, 0, 100, 50);
scene->addItem(item);
- 使用场景:当需要自定义矩形的交互行为或绘制外观时。
三、总结比较
表格:关键区别和适用场景
类别 | QLine / QRect | QPainterPath | QGraphicsPathItem / QGraphicsRectItem | 自定义 QGraphicsItem |
---|---|---|---|---|
定义 | 基础几何类,表示直线段和矩形区域 | 绘图路径类,描述复杂路径 | 图形项类,在场景中显示图形 | 继承图形项,添加自定义行为 |
特点 | 轻量级,整数精度,不支持交互 | 灵活构建复杂路径,浮点精度,支持布尔运算 | 可视化,支持交互和变换,属性可设置 | 可扩展性强,重写事件和绘制方法 |
使用场景 | 几何计算,基本绘制,布局计算 | 复杂形状绘制,路径动画,精确碰撞检测 | 图形编辑器,数据可视化,游戏开发 | 定制交互,特定功能组件,动画效果 |
交互性 | 不支持交互,需要手动处理 | 不支持交互,需要手动处理 | 支持交互,如选择、移动、缩放 | 支持自定义交互,重写事件处理 |
绘制方式 | 使用 QPainter 在小部件上绘制 | 使用 QPainter 绘制复杂形状 | 在 QGraphicsScene 中绘制 | 在 QGraphicsScene 中绘制,自定义绘制 |
通过以上对比,可以根据具体需求选择合适的类:
- 需要简单的几何计算或基本形状的数据表示时,使用 QLine 和 QRect。
- 需要绘制复杂路径或形状时,使用 QPainterPath。
- 需要在图形场景中显示和操作图形对象时,使用 QGraphicsPathItem 或 QGraphicsRectItem。
- 当标准图形项无法满足需求,需要特殊行为或外观时,通过继承创建自定义的 QGraphicsItem。
四、自定义 QGraphicsRectItem、自定义 QGraphicsPathItem 与自定义 QGraphicsItem 的区别
4.1 继承层次与基础功能
-
自定义 QGraphicsRectItem / QGraphicsPathItem:
- 继承关系:QGraphicsRectItem 和 QGraphicsPathItem 都是 QGraphicsItem 的子类。
- 基础功能:
- 默认实现:它们已经实现了 QGraphicsItem 的一些纯虚函数,如 boundingRect()、paint()、shape() 等。
- 几何形状:自带特定的几何形状(矩形或路径),并提供了相应的属性和方法操作这些形状。
- 绘制逻辑:默认实现了绘制逻辑,可直接用于显示。
-
自定义 QGraphicsItem:
- 继承关系:直接继承自 QGraphicsItem。
- 基础功能:
- 需要自行实现:必须实现所有纯虚函数,包括 boundingRect()、paint()、shape() 等。
- 完全自定义:具有最大的灵活性,可以定义任意的形状、绘制逻辑和交互行为。
4.2 差异对比
方面 | 自定义 QGraphicsRectItem / QGraphicsPathItem | 自定义 QGraphicsItem |
---|---|---|
开发复杂度 | - 较低:因为继承自已有的形状类,省去了实现基本功能的工作量。 - 快速上手:只需重写需要定制的部分。 | - 较高:需要从零开始实现所有必要的函数,包括几何计算和绘制逻辑。 |
灵活性 | - 有限:受到父类形状的限制,只能操作矩形或路径。 - 定制范围:适合在已有形状基础上稍作修改。 | - 最大:完全自主定义形状、外观和交互行为,可实现复杂和独特的图形项。 |
性能 | - 较优:父类已经对常见操作进行了优化。 - 资源占用:较低的资源消耗。 | - 视实现而定:需要注意优化,避免不必要的性能开销。 |
适用场景 | - 简单定制:当图形项是矩形或路径,并需要在此基础上增加少量功能或修改。 - 快速开发:节省时间和精力。 | - 复杂需求:当需要实现特殊形状或复杂的交互行为,无法通过继承现有类来实现时。 |
五、使用场景与示例
5.1 自定义 QGraphicsRectItem
使用场景:
- 当需要在矩形基础上增加特定功能,例如:
- 添加鼠标交互,响应点击、拖动等事件。
- 改变绘制方式,绘制特殊的边框或填充效果。
- 增加属性,例如关联数据等。
示例:创建一个可拖动的矩形,并在被点击时改变颜色。
class CustomRectItem : public QGraphicsRectItem {
public:
CustomRectItem(const QRectF &rect) : QGraphicsRectItem(rect) {
setFlags(ItemIsSelectable | ItemIsMovable);
setBrush(Qt::blue);
}
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override {
setBrush(Qt::red); // 点击时变为红色
QGraphicsRectItem::mousePressEvent(event); // 调用父类处理
}
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override {
setBrush(Qt::blue); // 释放时变回蓝色
QGraphicsRectItem::mouseReleaseEvent(event);
}
};
5.2 自定义 QGraphicsPathItem
使用场景:
- 当需要在路径基础上增加功能,例如:
- 实现路径的动画效果。
- 根据数据动态生成路径形状。
- 增加交互,支持节点的拖动、编辑等。
示例:创建一个可编辑的折线路径,支持节点拖动。
class EditablePathItem : public QGraphicsPathItem {
public:
EditablePathItem(const QPainterPath &path) : QGraphicsPathItem(path) {
setFlags(ItemIsSelectable | ItemIsMovable);
}
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override {
// 实现节点选择和拖动逻辑
}
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override {
// 更新路径形状
}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override {
// 自定义绘制,例如在节点处绘制控制点
QGraphicsPathItem::paint(painter, option, widget);
}
};
5.3 自定义 QGraphicsItem
使用场景:
- 当需要完全自定义的图形项,无法通过继承现有形状类实现。
- 需要特殊的形状、复杂的交互,或独特的绘制效果。
示例:创建一个自定义形状的图形项,例如五角星形状,并实现旋转动画。
class StarItem : public QGraphicsItem {
public:
StarItem() {
// 启动定时器,实现旋转动画
angle = 0;
timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &StarItem::rotate);
timer->start(100);
}
QRectF boundingRect() const override {
return QRectF(-50, -50, 100, 100); // 定义边界矩形
}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override {
painter->save();
painter->rotate(angle); // 旋转
painter->setBrush(Qt::yellow);
painter->drawPolygon(starPolygon()); // 绘制五角星
painter->restore();
}
QPainterPath shape() const override {
QPainterPath path;
path.addPolygon(starPolygon());
return path;
}
private:
QPolygonF starPolygon() const {
QPolygonF polygon;
// 计算五角星的顶点坐标
for (int i = 0; i < 5; ++i) {
qreal theta = (i * 72 - 90) * M_PI / 180;
qreal x = 40 * cos(theta);
qreal y = 40 * sin(theta);
polygon << QPointF(x, y);
}
return polygon;
}
void rotate() {
angle += 5;
if (angle >= 360) angle = 0;
update();
}
qreal angle;
QTimer *timer;
};
六、总结与选择建议
6.1 何时选择自定义 QGraphicsRectItem / QGraphicsPathItem
-
优势:
- 快速开发:利用已有的形状和功能,减少编码量。
- 简单可靠:继承自经过测试的类,稳定性有保障。
- 易于维护:代码结构清晰,易于理解和修改。
-
适用情况:
- 形状固定:图形项的基本形状是矩形或路径,不需要改变。
- 功能扩展:在现有功能上增加少量特性,如交互或绘制效果。
- 性能要求高:利用父类的优化,确保性能。
6.2 何时选择自定义 QGraphicsItem
-
优势:
- 无限灵活:可完全自定义形状、绘制和交互。
- 满足特殊需求:能够实现复杂和独特的图形效果。
- 深度优化:可以针对特定需求进行性能优化。
-
适用情况:
- 形状特殊:图形项的形状无法由现有类描述,需要完全自定义。
- 复杂交互:需要实现复杂的事件处理和用户交互逻辑。
- 独特绘制:需要超出常规的绘制效果,如动态变化、特效等。
6.3 选择建议
-
若图形项是现有形状的扩展,且只需增加少量功能,建议继承 QGraphicsRectItem 或 QGraphicsPathItem。
- 示例:在矩形上添加点击事件,或在路径上增加动画效果。
-
若图形项需求复杂,无法通过继承现有形状类来满足,建议直接继承 QGraphicsItem。
- 示例:创建复杂的自定义形状,或需要完全控制绘制和交互行为。