Qt实现绘图系统

文章目录

  • 环境
  • 功能模块
  • 总体设计
  • 界面
  • 部分功能介绍
  • 代码

环境

QT5.3

功能模块

 

总体设计

设计使用了Graphics View绘图架构,是一种基于图形项(Graphicsltem)的模型/视图模式,使用Graphics View架构可以绘制复杂的有几万个基本图形元件的图形,并且每个图形元件是可选择、可拖放和修改的,类似于矢量绘图软件的绘图功能。Graphics View架构主要由3个部分组成,即场景、视图和图形项,其构成的Graphics View绘图系统结构如图所示。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,C++设计模式,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

  

界面

 

 

部分功能介绍

1.选中后双击显示长度或面积

2.平移时选中显示平移对话框

 

缺点

保存文件时未保存线宽信息

代码

1、头文件

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QLabel>
#include <QGraphicsScene>
#include <QGraphicsItemGroup>
#include "translatedialog.h"

namespace Ui {
class MainWindow;
}

enum Status {
             Select,
             Fill,
             Translate,
             Delete,
             DrawLine,
             DrawRect,
             DrawEllipse,
             DrawPolygon,
             DrawCurve,
             DrawBrokenLine,
             Files // 文件操作
           };

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    bool save(QString &FileName);
    bool open(QString &FileName);



public slots:
    // 鼠标槽函数
    void mousePressed_slot(QMouseEvent *);
    void mouseMove_slot(QMouseEvent *);
    void mouseReleased_slot(QMouseEvent *);
    void mouseDoubleClick_slot(QMouseEvent *);

    // 保存,新建,打开
    void actNew_triggered_slot();
    void actSave_triggered_slot();
    void actOpen_triggered_slot();

    // 关闭
    void closeEvent(QCloseEvent *);



private:
    const int areaORlen_key = 1;  // 图形项长度/面积关键字
    const int shape_key = 2;  // 图形项类型关键字

    int group_id = 0;
    const int group_id_key = 3;  // 组合id关键字

    bool isSaved; // 是否保存


private:
    Ui::MainWindow *ui;

    Status cur_status;  // 当前状态

    QLabel shapeinfo_label; // 图形信息标签
    QLabel coordinate_label;  // 坐标标签

    QGraphicsScene  *scene;  // 场景

    QPointF start_point; // 绘制图形时的起点
    QPointF end_point;

    QVector<QPointF> points; // 绘制多边形时使用

    TranslateDialog *tDialog; // 平移对话框

    QGraphicsItemGroup *group; // 曲线组合

};

#endif // MAINWINDOW_H

mygraphicsview.h

#ifndef MYGRAPHICSVIEW_H
#define MYGRAPHICSVIEW_H

#include <QGraphicsView>

enum STATUS{ Edit,
             Draw,
             File
           };


class MyGraphicsview : public QGraphicsView
{
    Q_OBJECT
public:
    explicit MyGraphicsview(QWidget *parent = 0);

    void set_cur_status(STATUS s) { status = s; }

private:
    void mouseMoveEvent(QMouseEvent *);
    void mousePressEvent(QMouseEvent *);
    void mouseReleaseEvent(QMouseEvent *);
    void mouseDoubleClickEvent(QMouseEvent *);

signals:
    void mouseMove(QMouseEvent *); //鼠标移动
    void mousePressed(QMouseEvent *); //鼠标单击
    void mouseReleased(QMouseEvent *);
    void mouseDoubleClick(QMouseEvent *); //双击事件
    void keyPress(QKeyEvent *); //按键事件


public slots:

private:
    STATUS status;
};

#endif // MYGRAPHICSVIEW_H

translatedialog.h

#ifndef TRANSLATEDIALOG_H
#define TRANSLATEDIALOG_H

#include <QDialog>

namespace Ui {
class TranslateDialog;
}

class TranslateDialog : public QDialog
{
    Q_OBJECT

public:
    explicit TranslateDialog(QWidget *parent = 0);
    ~TranslateDialog();
signals:
    void translate_value(float x, float y);

private:
    Ui::TranslateDialog *ui;
};

#endif // TRANSLATEDIALOG_H

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,C++设计模式,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

2、源文件

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QStatusBar>
#include <QLabel>
#include <QPoint>
#include <QGraphicsScene>
#include <QMouseEvent>
#include <QDebug>
#include <QGraphicsLineItem>
#include <QGraphicsRectItem>
#include <QGraphicsPathItem>
#include <QGraphicsPolygonItem>
#include <QGraphicsItemGroup>
#include <QLine>
#include <QGraphicsView>
#include <QColor>
#include <QColorDialog>
#include <QMessageBox>
#include <QVector>
#include <QPointF>
#include <QFile>
#include <QDir>
#include <QFileDialog>
#include <QDataStream>
#include <QList>
#include <QMap>
#include <QToolBar>

#define PI 3.1415926


template<class T>
void setBrushColor(T *item)
{//函数模板
    QColor color = item->brush().color();
    color = QColorDialog::getColor(color,NULL,"选择填充颜色");
    if (color.isValid())
        item->setBrush(QBrush(color));
}

//计算任意多边形的面积,顶点按照顺时针或者逆时针方向排列
double ComputePolygonArea(const QVector<QPointF> &points)
{
    int point_num = points.size();
    if (point_num < 3) return 0.0;
    double s = points[0].y() * (points[point_num-1].x() - points[1].x());
    for(int i = 1; i < point_num; ++i)
        s += points[i].y() * (points[i-1].x() - points[(i+1)%point_num].x());
    return fabs(s/2.0);
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // 设置初始状态
    cur_status = Files;
    isSaved = false;
    // 设置状态栏
    QStatusBar *sBar = statusBar();
    coordinate_label.setParent(this);
    coordinate_label.setMinimumWidth(150);
    shapeinfo_label.setParent(this);
    shapeinfo_label.setMinimumWidth(200);
    sBar->addPermanentWidget(&coordinate_label);
    sBar->addPermanentWidget(&shapeinfo_label);

    // 设置工具栏
    QToolBar *tBar1 = addToolBar("文件工具栏");
    tBar1->addAction(ui->actionNew);
    tBar1->addSeparator();
    tBar1->addAction(ui->actionOpen);
    tBar1->addSeparator();
    tBar1->addAction(ui->actionSave);
    QToolBar *tBar2 = addToolBar("绘图工具栏");
    tBar2->addAction(ui->actionLine);
    tBar2->addSeparator();
    tBar2->addAction(ui->actionRectangle);
    tBar2->addSeparator();
    tBar2->addAction(ui->actionEllipse);
    tBar2->addSeparator();
    tBar2->addAction(ui->actionPolygon);
    tBar2->addSeparator();
    tBar2->addAction(ui->actionCurve);
    tBar2->addSeparator();
    tBar2->addAction(ui->action_broken_line);
    QToolBar *tBar3 = addToolBar("编辑工具栏");
    tBar3->addAction(ui->actionSelect);
    tBar3->addSeparator();
    tBar3->addAction(ui->actionFill);
    tBar3->addSeparator();
    tBar3->addAction(ui->actionTranslate);
    tBar3->addSeparator();
    tBar3->addAction(ui->actionDelete);

    ui->actionLine->setIcon(QIcon(":/image/images/LINE.BMP"));
    ui->actionCurve->setIcon(QIcon(":/image/images/ARC.BMP"));
    ui->actionEllipse->setIcon(QIcon(":/image/images/ELLIPSE.BMP"));
    ui->actionRectangle->setIcon(QIcon(":/image/images/RECTANGL.BMP"));
    ui->actionPolygon->setIcon(QIcon(":/image/images/FREEFORM.BMP"));
    ui->action_broken_line->setIcon(QIcon(":/image/images/brokenline.jpeg"));
    ui->actionSelect->setIcon(QIcon(":/image/images/select.jpeg"));
    ui->actionTranslate->setIcon(QIcon(":/image/images/522.bmp"));
    ui->actionFill->setIcon(QIcon(":/image/images/hmsetup.ico"));
    ui->actionDelete->setIcon(QIcon(":/image/images/DELETE.BMP"));
    ui->actionNew->setIcon(QIcon(":/image/images/new.jpeg"));
    ui->actionOpen->setIcon(QIcon(":/image/images/open.jpeg"));
    ui->actionSave->setIcon(QIcon(":/image/images/save.jpeg"));
    // 创建场景
    scene = new QGraphicsScene(-300,-200,600,200);
    ui->graphicsView->setScene(scene);

    // 设置鼠标样式
    ui->graphicsView->setMouseTracking(true);

    // 信号与槽
    connect(ui->graphicsView, &MyGraphicsview::mouseMove, this, &MainWindow::mouseMove_slot);
    connect(ui->graphicsView, &MyGraphicsview::mousePressed, this, &MainWindow::mousePressed_slot);
    connect(ui->graphicsView, &MyGraphicsview::mouseReleased, this, &MainWindow::mouseReleased_slot);
    connect(ui->graphicsView, &MyGraphicsview::mouseDoubleClick, this, &MainWindow::mouseDoubleClick_slot);


    connect(ui->actionLine, &QAction::triggered,
            [=]()
            {
                cur_status = DrawLine;
                shapeinfo_label.setText("");
                start_point = end_point = QPointF();
            }
            );
    connect(ui->actionLine, &QAction::triggered,
            ui->graphicsView,
            [=]()
            {
                ui->graphicsView->set_cur_status(Draw);
            }
            );
    connect(ui->actionRectangle, &QAction::triggered,
            [=]()
            {
                cur_status = DrawRect;
                shapeinfo_label.setText("");
                start_point = end_point = QPointF();
            }
            );
    connect(ui->actionRectangle, &QAction::triggered,
            ui->graphicsView,
            [=]()
            {
                ui->graphicsView->set_cur_status(Draw);
            }
            );
    connect(ui->actionEllipse, &QAction::triggered,
            [=]()
            {
                cur_status = DrawEllipse;
                shapeinfo_label.setText("");
                start_point = end_point = QPointF();
            }
            );
    connect(ui->actionEllipse, &QAction::triggered,
            ui->graphicsView,
            [=]()
            {
                ui->graphicsView->set_cur_status(Draw);
            }
            );
    connect(ui->actionPolygon, &QAction::triggered,
            [=]()
            {
                cur_status = DrawPolygon;
                shapeinfo_label.setText("");
                start_point = end_point = QPointF();
                points.clear();
            }
            );
    connect(ui->actionPolygon, &QAction::triggered,
            ui->graphicsView,
            [=]()
            {
                ui->graphicsView->set_cur_status(Draw);
            }
            );
    connect(ui->actionCurve, &QAction::triggered,
            [=]()
            {
                cur_status = DrawCurve;
                shapeinfo_label.setText("");
                start_point = end_point = QPointF();
            }
            );
    connect(ui->actionCurve, &QAction::triggered,
            ui->graphicsView,
            [=]()
            {
                ui->graphicsView->set_cur_status(Draw);
            }
            );

    connect(ui->action_broken_line, &QAction::triggered,
            [=]()
            {
                cur_status = DrawBrokenLine;
                shapeinfo_label.setText("");
                start_point = end_point = QPointF();
                points.clear();
            }
            );
    connect(ui->action_broken_line, &QAction::triggered,
            ui->graphicsView,
            [=]()
            {
                ui->graphicsView->set_cur_status(Draw);
            }
            );

    connect(ui->actionSelect, &QAction::triggered,
            [=]()
            {
                cur_status = Select;
            }
            );
    connect(ui->actionSelect, &QAction::triggered,
            ui->graphicsView,
            [=]()
            {
                ui->graphicsView->set_cur_status(Edit);
            }
            );
    connect(ui->actionFill, &QAction::triggered,
            [=]()
            {
                cur_status = Fill;
            }
            );
    connect(ui->actionFill, &QAction::triggered,
            ui->graphicsView,
            [=]()
            {
                ui->graphicsView->set_cur_status(Edit);
            }
            );
    connect(ui->actionTranslate, &QAction::triggered,
            [=]()
            {
                cur_status = Translate;
            }
            );
    connect(ui->actionTranslate, &QAction::triggered,
            ui->graphicsView,
            [=]()
            {
                ui->graphicsView->set_cur_status(Edit);
            }
            );
    connect(ui->actionDelete, &QAction::triggered,
            [=]()
            {
                cur_status = Delete;
            }
            );
    connect(ui->actionDelete, &QAction::triggered,
            ui->graphicsView,
            [=]()
            {
                ui->graphicsView->set_cur_status(Edit);
            }
            );

    connect(ui->actionNew, &QAction::triggered, this, &MainWindow::actNew_triggered_slot);
    connect(ui->actionNew, &QAction::triggered,
            ui->graphicsView,
            [=]()
            {
                ui->graphicsView->set_cur_status(File);
            }
            );
    connect(ui->actionSave, &QAction::triggered, this, &MainWindow::actSave_triggered_slot);
    connect(ui->actionSave, &QAction::triggered,
            ui->graphicsView,
            [=]()
            {
                ui->graphicsView->set_cur_status(File);
            }
            );
    connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::actOpen_triggered_slot);
    connect(ui->actionOpen, &QAction::triggered,
            ui->graphicsView,
            [=]()
            {
                ui->graphicsView->set_cur_status(File);
            }
            );
}

MainWindow::~MainWindow()
{
    delete group;
    delete scene;
    delete ui;
}

void MainWindow::mousePressed_slot(QMouseEvent *e) {
    if (e->button() == Qt::LeftButton) {
        // 绘图时
        if (cur_status == DrawLine
                || cur_status == DrawRect
                || cur_status == DrawEllipse
                || cur_status == DrawPolygon
                || cur_status == DrawCurve
                || cur_status == DrawBrokenLine)
        {
            isSaved = false;
            start_point = ui->graphicsView->mapToScene(e->pos());
            if (cur_status == DrawPolygon) {
                points.append(start_point);
            }
            if (cur_status == DrawCurve) { // 曲线
                group = new QGraphicsItemGroup; // 创建一个组合
                scene->addItem(group);
                group->setData(areaORlen_key, QVariant(0.0));
                group->setData(shape_key, "曲线");
                group->setData(group_id_key, group_id);
            }
            if (cur_status == DrawBrokenLine) {
                if (points.isEmpty()) { // 点下第一个点时
                    group = new QGraphicsItemGroup; // 创建一个组合
                    scene->addItem(group);
                    group->setData(areaORlen_key, QVariant(0.0));
                    group->setData(shape_key, "折线段");
                    group->setData(group_id_key, group_id);
                }
                points.append(start_point);
            }
        }
        // 编辑时
        else if (cur_status == Select
                 || cur_status == Fill
                 || cur_status == Translate
                 || cur_status == Delete)
        {
            isSaved = false;
            // 先选中
            QPointF pointScene = ui->graphicsView->mapToScene(e->pos()); //转换到Scene坐标
            QGraphicsItem *item = NULL;
            item = scene->itemAt(pointScene, ui->graphicsView->transform()); //获取光标下的绘图项
            if (item) {
                if (item->group()) {
                    item = item->group();
                }
                // 状态栏显示长度/面积
                item->setCursor(Qt::SizeAllCursor); // 改变鼠标样式

                QString shapeinfo = "面积";
                if (item->data(shape_key).toString() == "直线"
                        || item->data(shape_key).toString() == "曲线"
                        || item->data(shape_key).toString() == "折线")
                    shapeinfo = "长度";
                QString str;
                if (item->group()) str = item->group()->data(areaORlen_key).toString();
                else str = item->data(areaORlen_key).toString();
                shapeinfo_label.setText(QString("选中对象: %1   " + shapeinfo + ": %2    ").arg(item->data(shape_key).toString()).arg(str));
            } else {
                shapeinfo_label.setText("");
                return;
            }

            if (cur_status == Fill) { // 填充
                switch (item->type())  //绘图项的类型
                {
                      case QGraphicsRectItem::Type: //矩形框
                      {
                        QGraphicsRectItem *theItem = qgraphicsitem_cast<QGraphicsRectItem*>(item);
                        setBrushColor(theItem);
                        break;
                      }
                      case QGraphicsEllipseItem::Type: // 椭圆
                      {
                        QGraphicsEllipseItem *theItem;
                        theItem = qgraphicsitem_cast<QGraphicsEllipseItem*>(item);
                        setBrushColor(theItem);
                        break;
                      }
                      case QGraphicsPolygonItem::Type: //多边形
                      {
                        QGraphicsPolygonItem *theItem = qgraphicsitem_cast<QGraphicsPolygonItem*>(item);
                        setBrushColor(theItem);
                        break;
                      }
                      case QGraphicsLineItem::Type: //直线,设置线条颜色
                      {
                        QGraphicsLineItem *theItem = qgraphicsitem_cast<QGraphicsLineItem*>(item);
                        QPen pen = theItem->pen();
                        QColor color = theItem->pen().color();
                        color = QColorDialog::getColor(color,this,"选择线条颜色");
                        if (color.isValid())
                        {
                            pen.setColor(color);
                            theItem->setPen(pen);
                        }
                        break;
                      }
                     case QGraphicsItemGroup::Type:
                     {
                        QGraphicsItemGroup *thegroup = qgraphicsitem_cast<QGraphicsItemGroup*>(item);
                        QColor color = QColorDialog::getColor(color,this,"选择线条颜色");
                        QList<QGraphicsItem *>	items_list = scene->items();
                        for (int i = 0; i < items_list.size(); i++) {
                            if (items_list[i]->type() == QGraphicsLineItem::Type
                                    && items_list[i]->data(group_id_key).toInt() == thegroup->data(group_id_key).toInt())
                            {
                                QGraphicsLineItem *theItem = qgraphicsitem_cast<QGraphicsLineItem*>(items_list[i]);
                                QPen pen = theItem->pen();
                                if (color.isValid())
                                {
                                    pen.setColor(color);
                                    theItem->setPen(pen);
                                }
                            }
                        }
                        break;
                     }
                }
                scene->clearSelection();
            }
            else if (cur_status == Translate) {  // 平移
                // 平移模态对话框
                tDialog = new TranslateDialog(this);
                // 接受信号,包含输入的平移量
                connect(tDialog, &TranslateDialog::translate_value,
                        [=](float x, float y)
                        {

                            item->setPos(QPointF(item->x() + x, item->y() + y));

                            //item->rect().setX(item->x() + x);





                        }
                        );
                tDialog->exec();
            }
            else if (cur_status == Delete) {  // 删除
                // 删除所选中的绘图项
                int cnt = scene->selectedItems().count();
                if (cnt > 0)
                for (int i = 0; i < cnt; i++) {
                    QGraphicsItem *item = scene->selectedItems().at(0);
                    scene->removeItem(item);
                }
            }
            scene->clearSelection();
        } else {  // 其他选项
            shapeinfo_label.setText("");
        }
    } else if (e->button() == Qt::RightButton) { // 鼠标右击 画多边形
        if (cur_status == DrawPolygon) {
            start_point = ui->graphicsView->mapToScene(e->pos());
            points.append(start_point);
            for (auto e : points) qDebug() << e.x() << e.y() << endl;

            // 画多边形
            QGraphicsPolygonItem *item = new QGraphicsPolygonItem(QPolygonF(points));
            item->setFlags(QGraphicsItem::ItemIsMovable
                           | QGraphicsItem::ItemIsSelectable
                           | QGraphicsItem::ItemIsFocusable);
            double area = ComputePolygonArea(points);
            item->setData(areaORlen_key, area);
            item->setData(shape_key, "多边形");
            scene->addItem(item);
            // 清空points容器,便于下一个多边形绘制
            points.clear();
        } else if (cur_status == DrawBrokenLine) {
            start_point = ui->graphicsView->mapToScene(e->pos());
            points.append(start_point);
            // 画折线
            for (int i = 0; i < points.size() - 1; i++) {
                QGraphicsLineItem *line_item = new QGraphicsLineItem(QLineF(points[i], points[i + 1]));//x,y 为左上角的图元局部坐标,图元中心点为0,0
                line_item->setFlags(QGraphicsItem::ItemIsMovable
                               | QGraphicsItem::ItemIsSelectable
                               | QGraphicsItem::ItemIsFocusable);

                QPen pen;
                pen.setWidth(2);
                line_item->setPen(pen);
                line_item->setSelected(false);
                line_item->clearFocus();
                line_item->setData(shape_key, "折线中直线");
                line_item->setData(group_id_key, group_id);
                // 计算长度
                double len = sqrt(pow((points[i].x() - points[i + 1].x()), 2) + pow((points[i].y() - points[i + 1].y()), 2));
                line_item->setData(areaORlen_key, len);
                group->setData(areaORlen_key, QVariant(group->data(areaORlen_key).toDouble() + len));
                // 加入到组合中
                group->addToGroup(qgraphicsitem_cast<QGraphicsItem*>(line_item));
            }
            points.clear();
            // 设置可选可移动
            group->setFlags(QGraphicsItem::ItemIsMovable
                           | QGraphicsItem::ItemIsSelectable
                           | QGraphicsItem::ItemIsFocusable);
            group->setSelected(false);
            group_id++;
        }
    }
}

void MainWindow::mouseMove_slot(QMouseEvent *e) {  // 鼠标移动过程中状态栏显示坐标
    QPointF point = ui->graphicsView->mapToScene(e->pos());
    coordinate_label.setText(QString("坐标:(%1, %2)").arg(point.x()).arg(point.y()));
    if (cur_status == DrawLine
            || cur_status == DrawRect
            || cur_status == DrawEllipse
            || cur_status == DrawPolygon
            || cur_status == DrawCurve
            || cur_status == DrawBrokenLine)
    {
        // 设置鼠标样式
        ui->graphicsView->setCursor(Qt::CrossCursor);
    }
    if ((e->buttons() & Qt::LeftButton) && cur_status == DrawCurve) { // 画曲线
        end_point = ui->graphicsView->mapToScene(e->pos());
        QGraphicsLineItem *line_item = new QGraphicsLineItem(QLineF(start_point, end_point));//x,y 为左上角的图元局部坐标,图元中心点为0,0
        line_item->setFlags(QGraphicsItem::ItemIsMovable
                       | QGraphicsItem::ItemIsSelectable
                       | QGraphicsItem::ItemIsFocusable);

        QPen pen;
        pen.setWidth(2);
        line_item->setPen(pen);
        line_item->setSelected(false);
        line_item->clearFocus();
        line_item->setData(shape_key, "曲线中直线");
        line_item->setData(group_id_key, group_id);


        // 计算长度
        double len = sqrt(pow((start_point.x() - end_point.x()), 2) + pow((start_point.y() - end_point.y()), 2));
        line_item->setData(areaORlen_key, len);
        group->setData(areaORlen_key, QVariant(group->data(areaORlen_key).toDouble() + len));
        scene->addItem(line_item);
        // 保存直线
        group->addToGroup(qgraphicsitem_cast<QGraphicsItem*>(line_item));
        start_point = end_point;
    }
}

void MainWindow::mouseReleased_slot(QMouseEvent *e) {  // 鼠标释放时绘制图形
    if (e->button() == Qt::LeftButton) {
        // 获取鼠标释放时的坐标
        end_point = ui->graphicsView->mapToScene(e->pos());
        switch(cur_status) {
        case DrawLine:  // 绘制直线
        {
            QGraphicsLineItem *line_item = new QGraphicsLineItem(QLineF(start_point, end_point));//x,y 为左上角的图元局部坐标,图元中心点为0,0
            line_item->setFlags(QGraphicsItem::ItemIsMovable
                           | QGraphicsItem::ItemIsSelectable
                           | QGraphicsItem::ItemIsFocusable);

            QPen pen;
            pen.setWidth(2);
            line_item->setPen(pen);
            // 计算长度
            double len = sqrt(pow((start_point.x() - end_point.x()), 2) + pow((start_point.y() - end_point.y()), 2));
            line_item->setData(areaORlen_key, QVariant(len));
            line_item->setData(shape_key, "直线");
            scene->addItem(line_item);
            break;
        }
        case DrawRect:  // 绘制矩形
        {
            // 保持start_point在左上方
            if (start_point.x() > end_point.x()) {
                QPointF tmp = start_point;
                start_point = end_point;
                end_point = tmp;
            }
            QGraphicsRectItem *rect_item = new QGraphicsRectItem(QRectF(start_point, end_point));//x,y 为左上角的图元局部坐标,图元中心点为0,0
            rect_item->setFlags(QGraphicsItem::ItemIsMovable
                           | QGraphicsItem::ItemIsSelectable
                           | QGraphicsItem::ItemIsFocusable);
            double area = (end_point.x() - start_point.x()) * (end_point.y() - start_point.y());
            rect_item->setData(areaORlen_key, QVariant(area));
            rect_item->setData(shape_key, "矩形");
            scene->addItem(rect_item);
            break;
        }
        case DrawEllipse:  // 绘制椭圆
        {
            // 保持start_point在左上方
            if (start_point.x() > end_point.x()) {
                QPointF tmp = start_point;
                start_point = end_point;
                end_point = tmp;
            }
            QGraphicsEllipseItem *item=new QGraphicsEllipseItem(QRectF(start_point, end_point));
            item->setFlags(QGraphicsItem::ItemIsMovable
                           | QGraphicsItem::ItemIsSelectable
                           | QGraphicsItem::ItemIsFocusable);
            double area = PI * (end_point.x() - start_point.x()) * 0.5 * (end_point.y() - start_point.y()) * 0.5;
            item->setData(areaORlen_key, area);
            item->setData(shape_key, "椭圆");
            scene->addItem(item);
            break;
        }
        case DrawCurve:{
            // 设置可选可移动
            group->setFlags(QGraphicsItem::ItemIsMovable
                           | QGraphicsItem::ItemIsSelectable
                           | QGraphicsItem::ItemIsFocusable);
            group_id++;
            break;
        }
        default:           
            break;
        }
    }
}

void MainWindow::mouseDoubleClick_slot(QMouseEvent *e) {  // 鼠标双击时显示长度/面积对话框
    if (cur_status == Select) {
        QPointF pointScene = ui->graphicsView->mapToScene(e->pos()); //转换到Scene坐标
        QGraphicsItem *item = NULL;
        item = scene->itemAt(pointScene, ui->graphicsView->transform()); //获取光标下的绘图项
        if (item) {

            QString shapeinfo = "面积";
            if (item->data(shape_key).toString() == "直线"
                    || item->data(shape_key).toString() == "曲线中直线"
                    || item->data(shape_key).toString() == "折线中直线"
                    || item->data(shape_key).toString() == "曲线"
                    || item->data(shape_key).toString() == "折线")
                shapeinfo = "长度";
            QString str;
            if (item->group()) str = item->group()->data(areaORlen_key).toString();
            else str = item->data(areaORlen_key).toString();
            QMessageBox::information(this, shapeinfo, str);
        }
    }
}

void MainWindow::actSave_triggered_slot() {
    cur_status = Files;
    //以Qt预定义编码保存数据文件
    QString curPath = QDir::currentPath();
    QString aFileName = QFileDialog::getSaveFileName(this, tr("选择保存文件"), curPath,
                                                   "Qt预定义编码数据文件(*.stm)");

    if (aFileName.isEmpty())
        return; //

    if  (save(aFileName)) {//保存为流数据文件
        QMessageBox::information(this, "提示消息", "文件已经成功保存!");
        isSaved = true;
    }
}

bool MainWindow::save(QString &FileName) {
    QFile file(FileName);
    if (!(file.open(QIODevice::WriteOnly | QIODevice::Truncate)))
        return false;
    QDataStream stream(&file);
    stream.setVersion(QDataStream::Qt_5_3);
    // 获取sence中的图形
    QList<QGraphicsItem *>	items_list = scene->items();
    // 保存数据
    for (int i = 0; i < items_list.size(); i++) {
        switch(items_list[i]->type())
        {
        case QGraphicsRectItem::Type: //矩形框
        {
            QGraphicsRectItem *theItem = qgraphicsitem_cast<QGraphicsRectItem*>(items_list[i]);
            stream << QString("矩形");
            stream << theItem->rect();
            stream << theItem->data(areaORlen_key).toDouble();
            if (theItem->brush() != QBrush()) stream << theItem->brush().color();
            else stream << QColor();
            break;
        }
        case QGraphicsEllipseItem::Type: // 椭圆
        {
            QGraphicsEllipseItem *theItem = qgraphicsitem_cast<QGraphicsEllipseItem*>(items_list[i]);
            stream << QString("椭圆");
            stream << theItem->rect();
            stream << theItem->data(areaORlen_key).toDouble();
            if (theItem->brush() != QBrush()) stream << theItem->brush().color();
            else stream << QColor();
            break;
        }
        case QGraphicsPolygonItem::Type: //多边形
        {
            QGraphicsPolygonItem *theItem = qgraphicsitem_cast<QGraphicsPolygonItem*>(items_list[i]);
            stream << QString("多边形");
            stream << theItem->polygon();
            stream << theItem->data(areaORlen_key).toDouble();
            if (theItem->brush() != QBrush()) stream << theItem->brush().color();
            else stream << QColor();
            break;
        }
        case QGraphicsLineItem::Type: //直线
        {
            QGraphicsLineItem *theItem = qgraphicsitem_cast<QGraphicsLineItem*>(items_list[i]);
            stream << QString("直线");
            stream << theItem->line();
            stream << theItem->data(areaORlen_key).toDouble();
            if (theItem->group()) {
                stream << theItem->group()->data(group_id_key).toInt();
            } else {
                stream << -1;
            }
            stream << theItem->data(shape_key).toString();
            stream << theItem->pen().color();
            break;
        }
        }
    }
    file.close();
    return true;
}

void MainWindow::actOpen_triggered_slot() {
    cur_status = Files;
    QString curPath=QDir::currentPath();
    //调用打开文件对话框打开一个文件
    QString aFileName=QFileDialog::getOpenFileName(this,tr("打开一个文件"),curPath,
                 "流数据文件(*.stm)");

    if (aFileName.isEmpty())
        return; //

    if  (open(aFileName)) //保存为流数据文件
         QMessageBox::information(this,"提示消息","文件已经打开!");
}

bool MainWindow::open(QString &FileName) {
    QFile file(FileName);
    if (!(file.open(QIODevice::ReadOnly)))
        return false;
    QDataStream stream(&file);
    stream.setVersion(QDataStream::Qt_5_3);
    scene->clear();
    group_id = 0;
    while (!file.atEnd())
    {
        QString type;
        stream >> type;
        if (type == "矩形")
        {
            QRectF rect;
            stream >> rect;
            QGraphicsRectItem *rect_item = new QGraphicsRectItem(rect);//x,y 为左上角的图元局部坐标,图元中心点为0,0
            rect_item->setFlags(QGraphicsItem::ItemIsMovable
                           | QGraphicsItem::ItemIsSelectable
                           | QGraphicsItem::ItemIsFocusable);
            double area;
            stream >> area;
            rect_item->setData(areaORlen_key, QVariant(area));
            rect_item->setData(shape_key, "矩形");
            scene->addItem(rect_item);

            QColor color;
            stream >> color;
            if (color.isValid())
                rect_item->setBrush(QBrush(color));
        }
        else if (type == "椭圆") // 椭圆
        {
            QRectF rect;
            stream >> rect;
            QGraphicsEllipseItem *item = new QGraphicsEllipseItem(rect);
            item->setFlags(QGraphicsItem::ItemIsMovable
                           | QGraphicsItem::ItemIsSelectable
                           | QGraphicsItem::ItemIsFocusable);
            double area;
            stream >> area;
            item->setData(areaORlen_key, area);
            item->setData(shape_key, "椭圆");
            scene->addItem(item);
            QColor color;
            stream >> color;
            if (color.isValid())
                item->setBrush(QBrush(color));
        }
        else if (type == "多边形") //多边形
        {
            QPolygonF polygon;
            stream >> polygon;
            QGraphicsPolygonItem *item = new QGraphicsPolygonItem(polygon);
            item->setFlags(QGraphicsItem::ItemIsMovable
                           | QGraphicsItem::ItemIsSelectable
                           | QGraphicsItem::ItemIsFocusable);
            double area;
            stream >> area;
            item->setData(areaORlen_key, area);
            item->setData(shape_key, "多边形");
            scene->addItem(item);
            QColor color;
            stream >> color;
            if (color.isValid())
                item->setBrush(QBrush(color));
        }
        else if (type == "直线") //直线
        {
            QLineF line;
            stream >> line;
            QGraphicsLineItem *line_item = new QGraphicsLineItem(line);//x,y 为左上角的图元局部坐标,图元中心点为0,0
            line_item->setFlags(QGraphicsItem::ItemIsMovable
                           | QGraphicsItem::ItemIsSelectable
                           | QGraphicsItem::ItemIsFocusable);

            QPen pen;
            pen.setWidth(2);
            line_item->setPen(pen);
            line_item->setSelected(false);
            line_item->clearFocus();
            // 计算长度
            double len;
            stream >> len;
            line_item->setData(areaORlen_key, QVariant(len));
            //line_item->setData(shape_key, "直线");
            int id;
            stream >> id;
            line_item->setData(group_id_key, id);
            QString shape;
            stream >> shape;
            line_item->setData(shape_key, shape);
            scene->addItem(line_item);

            QColor color;
            stream >> color;
            if (color.isValid())
                line_item->setPen(QPen(color));
        }
        // 恢复曲线和折线
        QList<QGraphicsItem *>	items_list = scene->items();
        QMap<int, QGraphicsItemGroup *> map;

        for (int i = 0; i < items_list.size(); i++) {
            if (items_list[i]->type() == QGraphicsLineItem::Type) {
                QGraphicsLineItem *theItem = qgraphicsitem_cast<QGraphicsLineItem*>(items_list[i]);
                int id = theItem->data(group_id_key).toInt();
                if (theItem->data(group_id_key).toInt() == -1) break;
                if (!map.count(id)) {
                    map[id] = new QGraphicsItemGroup;
                    QString shape;
                    if (theItem->data(shape_key).toString() == "曲线中直线") {
                        shape = "曲线";
                    } else {
                        shape = "折线";
                        //map[id]->setData(brokenline_id_key, brokenline_id++);
                    }
                    map[id]->setData(shape_key, shape);
                    map[id]->setData(group_id_key, id);
                    map[id]->setData(areaORlen_key, QVariant(0.0));
                    scene->addItem(map[id]);
                }

                map[id]->addToGroup(qgraphicsitem_cast<QGraphicsItem*>(theItem));


                map[id]->setData(areaORlen_key, theItem->data(areaORlen_key).toDouble() + map[id]->data(areaORlen_key).toDouble());



            }
        }
        for (QMap<int, QGraphicsItemGroup*>::iterator iter = map.begin(); iter != map.end(); iter++) {
            iter.value()->setFlags(QGraphicsItem::ItemIsMovable
                                  | QGraphicsItem::ItemIsSelectable
                                  | QGraphicsItem::ItemIsFocusable);
            iter.value()->setSelected(false);
        }
    }


    file.close();
    return true;
}


void MainWindow::actNew_triggered_slot() {
    if (scene->items().size() && !isSaved) {
        // 先询问是否保存
        int ans = QMessageBox::question(this, "提示", "当前文件未保存,是否先保存?");
        if (ans == QMessageBox::Yes) {
            //以Qt预定义编码保存数据文件
            QString curPath = QDir::currentPath();
            QString aFileName = QFileDialog::getSaveFileName(this, tr("选择保存文件"), curPath,
                                                           "Qt预定义编码数据文件(*.stm)");

            if (aFileName.isEmpty())
                return; //

            if  (save(aFileName)) {//保存为流数据文件
                QMessageBox::information(this, "提示消息", "文件已经成功保存!");
                isSaved = true;
            }
        }
    }
    scene->clear();
    group_id = 0;
}

void MainWindow::closeEvent(QCloseEvent *) {
    if (scene->items()mygraphicsview.cpp.size() && !isSaved) {
        // 先询问是否保存
        int ans = QMessageBox::question(this, "提示", "当前文件未保存,是否先保存?");
        if (ans == QMessageBox::Yes) {
            //以Qt预定义编码保存数据文件
            QString curPath = QDir::currentPath();
            QString aFileName = QFileDialog::getSaveFileName(this, tr("选择保存文件"), curPath,
                                                           "Qt预定义编码数据文件(*.stm)");

            if (aFileName.isEmpty())
                return; //

            if  (save(aFileName)) {//保存为流数据文件
                QMessageBox::information(this, "提示消息", "文件已经成功保存!");
                isSaved = true;
            }
        }
    }
}

mygraphicsview.cpp

#include "mygraphicsview.h"
#include <QMouseEvent>
#include <QPoint>
#include <QDebug>

MyGraphicsview::MyGraphicsview(QWidget *parent) :
    QGraphicsView(parent)
{
    status = File;
}

void MyGraphicsview::mousePressEvent(QMouseEvent *e) {
    emit mousePressed(e);
    if (status == Edit) { // 事件继续传递该父类QGraphicsView
        QGraphicsView::mousePressEvent(e);
    }
}

void MyGraphicsview::mouseMoveEvent(QMouseEvent *e) {
    emit mouseMove(e);
    if (status == Edit) {
        QGraphicsView::mouseMoveEvent(e);
    }
}

void MyGraphicsview::mouseReleaseEvent(QMouseEvent *e) {
    emit mouseReleased(e);
    if (status == Edit) {
        QGraphicsView::mouseReleaseEvent(e);
    }
}

void MyGraphicsview::mouseDoubleClickEvent(QMouseEvent *e) {
    emit mouseDoubleClick(e);
    QGraphicsView::mouseDoubleClickEvent(e);
}



translatedialog.cpp

#include "translatedialog.h"
#include "ui_translatedialog.h"
#include <QDialogButtonBox>
#include <QPushButton>

TranslateDialog::TranslateDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::TranslateDialog)
{
    ui->setupUi(this);
    // 对话框按键时发出信号,包括平移量
    connect(ui->buttonBox, &QDialogButtonBox::clicked,
           [=](QAbstractButton * button)
            {
                float x, y;
                if(ui->buttonBox->button(QDialogButtonBox::Ok) == static_cast<QPushButton *>(button)) {  //判断按下的是否为"确定”按钮
                    if(!ui->lineEdit->text().isEmpty() && !ui->lineEdit_2->text().isEmpty())  //判断lineEdit是否为空
                    {
                        x = ui->lineEdit->text().toFloat();
                        y = ui->lineEdit_2->text().toFloat();
                        emit translate_value(x, y);
                    }
                }
            }
            );
}

TranslateDialog::~TranslateDialog()
{
    delete ui;
}

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,C++设计模式,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

猜你喜欢

转载自blog.csdn.net/m0_73443478/article/details/131808977
今日推荐