目录
前言:
对于上一节没有完成的功能进行续写,对ui界面进行简单的修改,添加了椭圆绘制,绘制图形保存在graphicsView中这两个功能,后续会对文字添加,清屏以及图片旋转功能进行添加。
基础夯实:
1.创建 QGraphicsScene 和 QGraphicsView
在你的主窗口或者相应的QWidget中,创建一个 QGraphicsScene 和一个 QGraphicsView。QGraphicsScene 是图形的容器,而 QGraphicsView 用于显示这个场景。
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsEllipseItem>
QGraphicsScene *scene = new QGraphicsScene(this);
QGraphicsView *view = new QGraphicsView(scene, this);
setCentralWidget(view); // 假设你在一个QMainWindow中
2. 在 QGraphicsScene 中添加椭圆
使用 QGraphicsEllipseItem 创建一个椭圆,并将其添加到 QGraphicsScene 中。你可以指定椭圆的矩形边界(使用 QRectF),或者简单地使用 x, y, width, height 参数。
QGraphicsEllipseItem *ellipse = scene->addEllipse(QRectF(10, 10, 100, 50), QPen(Qt::black), QBrush(Qt::blue));
// 或者
// QGraphicsEllipseItem *ellipse = scene->addEllipse(10, 10, 100, 50);
// 然后你可以设置它的笔和刷
// ellipse->setPen(QPen(Qt::black));
// ellipse->setBrush(QBrush(Qt::blue));
3. 渲染和显示
将 QGraphicsView 添加到你的窗口或布局中后,它就会自动显示 QGraphicsScene 中的所有图形项,包括你刚刚添加的椭圆。
4. 推荐学习本文之前查看的链接:
效果展示:
实现功能:
实现了添加了椭圆绘制,绘制图形保存的graphicsView中这两个功能。
遇到问题:
一种图形只能添加一次,不能连续添加。图片无法保存到视图中。
核心代码:
//CustomGraphicsView.cpp
#include "CustomGraphicsView.h"
#include <QGraphicsRectItem>
#include <QGraphicsScene>
#include <QMouseEvent>
CustomGraphicsView::CustomGraphicsView(QWidget *parent)
: QGraphicsView(parent)
{
}
void CustomGraphicsView::setDrawMode(DrawMode mode)
{
currentDrawMode = mode;
}
// 辅助函数,用于创建新的椭圆项
QGraphicsEllipseItem* CustomGraphicsView::createEllipseItem(const QRectF &rect, const QPen &pen, const QBrush &brush)
{
QGraphicsEllipseItem *item = new QGraphicsEllipseItem(rect);
item->setPen(pen);
item->setBrush(brush);
scene()->addItem(item);
ellipseItems.append(item);
return item;
}
void CustomGraphicsView::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
isDrawing = true;
startPoint = mapToScene(event->pos());
switch (currentDrawMode) {
case RectMode:
// 矩形模式下,初始化矩形的两个角(实际上是同一个点,稍后在move事件中更新)
rectItem = new QGraphicsRectItem(QRectF(startPoint, QSizeF(0, 0)));
rectItem->setPen(QPen(Qt::blue)); // 示例颜色
scene()->addItem(rectItem);
break;
case LineMode:
// 线条模式下,不立即绘制线条,只在move事件中根据起点和当前点绘制
lineItem = nullptr; // 如果之前有线条,则忽略它(或根据需要重置)
break;
case EllipseMode:
if (!ellipseItem) {
QRectF ellipseRect(startPoint, QSizeF(0, 0)); // 初始大小为0,稍后在move事件中更新
ellipseItem = createEllipseItem(ellipseRect, QPen(Qt::green), QBrush(Qt::NoBrush));
}
// 否则,不创建新项,只更新startPoint
break;
default:
// ...
break;
}
emit mouseClicked(event->pos());
}
QGraphicsView::mousePressEvent(event);
}
void CustomGraphicsView::mouseMoveEvent(QMouseEvent *event)
{
if (isDrawing) {
QPointF endPoint = mapToScene(event->pos());
switch (currentDrawMode) {
case RectMode:
{
QPointF topLeft = QPointF(qMin(startPoint.x(), endPoint.x()), qMin(startPoint.y(), endPoint.y()));
QPointF bottomRight = QPointF(qMax(startPoint.x(), endPoint.x()), qMax(startPoint.y(), endPoint.y()));
rectItem->setRect(QRectF(topLeft, bottomRight));
break;
}
case LineMode:
{
if (!lineItem) {
lineItem = scene()->addLine(startPoint.x(), startPoint.y(), endPoint.x(), endPoint.y(), QPen(Qt::red));
} else {
lineItem->setLine(QLineF(startPoint, endPoint));
}
break;
}
case EllipseMode:
{
QPointF topLeft = QPointF(qMin(startPoint.x(), endPoint.x()), qMin(startPoint.y(), endPoint.y()));
QPointF bottomRight = QPointF(qMax(startPoint.x(), endPoint.x()), qMax(startPoint.y(), endPoint.y()));
QRectF ellipseRect(topLeft, QSizeF(bottomRight.x() - topLeft.x(), bottomRight.y() - topLeft.y()));
if (ellipseItem) {
ellipseItem->setRect(ellipseRect);
}
break;
}
default:
// 处理默认情况
break;
}
}
emit mouseMoved(event->pos());
}
void CustomGraphicsView::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton && isDrawing) {
isDrawing = false;
}
emit mouseReleased(event->pos());
//重置模型项,以便下一次重写
switch (currentDrawMode) {
case RectMode:
rectItem = nullptr;
break;
case LineMode:
lineItem = nullptr;
break;
case EllipseMode:
ellipseItem = nullptr;
break;
}
QGraphicsView::mouseReleaseEvent(event);
}
仓库源码:
代码在之前的链接中进行详细展示了,这里把源码放仓库了,欢迎二次开发:
https://gitee.com/wangning719/drawing