文章目录
- 环境
- 功能模块
- 总体设计
- 界面
- 部分功能介绍
- 代码
环境
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模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击莬费领取↓↓