注:本人学习阶段,仅供参考。如有错误,请指正,谢谢!
一、简单介绍GraphicsView框架
Graphics View框架实现了模型到视图结构的图形管理,能对大量图元进行管理,支持坐标变换和图元组等多种方便的功能。
框架结构三个主要的类:
1)场景类:QGraphicsScene类(管理多个图形项,用于放置图元的容器,但本身不可见)
2)视图类:QGraphicsView类(提供可视窗口,显示场景中的图元,一个场景中有多个视图)
3)图元类:QGraphicsItem类(各个图元的基础类,QT提供了常用图元的标准类)
三元素关系
QGraphicsItem(图形项) -----addItem()------>QGraphicsScene(图形项的容器,场景)--------setScene()------>QGraphicsView(可视化使场景中的内容)
三元素坐标系
QGraphicsView提供QGraphicsView::mapToScene()和QGraphicsView:: mapFromScene()函数用于视图与场景的坐标进行转换
QT提供常用图元标准类
当然,也可以在QGraphicsItem类的基础上实现自定义的图元类,即用户可以继承QGraphicsItem实现符合自己需要的图元。
- QGraphicsLineItem 用来绘制直线,可以通过setLine(const QLineF&)来添加。
- QGraphicsRectItem 用来绘制矩形,通过setRect()来进行添加
- QGraphicsEllipseItem 用来绘制椭圆,或者部分椭圆。通过设置setStartAngle(int)和setSpanAngle(int)可以绘制椭圆的一部分。设置的值是1度的1/16。
- QGraphicsPolygonItem 用来绘制多边形,通过setPolygon()添加
- QGraphicsPathItem 绘制一个路径,通过setPath()来进行添加
- QGraphicsSimpleTextItem 绘制简单文本,除了可以设置字体以外,不支持其它的富文本样式
- QGraphicsTextItem 绘制格式化的文本,可以通过setHtml()或者setDocument()设置html,还可以添加有交互内容的URL超链接。
- QGraphicsPixmapItem 绘制图片,或者渲染一个图片
- QGraphicsProxyWidget 绘制任意的QWdiget控件,视图框架允许我们与添加的控件进行交互。
二、Graphic图形编辑器
这是一个简单的图形编辑器,它只对视图部分进行了部分重写。添加了各种图元,如圆、椭圆、矩形、文本、图片等,可进行旋转、放大、缩小、前置、后置、组合、散开、删除等功能。
在代码中有很多地方添加了注释,这里就不一一赘述了。
效果展示:
源码展示:
ui界面:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QGraphicsScene>
#include <QLabel>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
static const int ItemId = 1; //绘图项自定义数据的key
static const int ItemDesciption = 2;//绘图自定义数据的key
int seqNum = 0;
int backZ = 0;
int frontZ = 0;
// bool isMode = true;
QPoint linePoint;
//直线
bool isline = true;
//矩形
bool isrectangle = true;
//三角形
bool isTriangle = true;
//椭圆
bool isEllipse= true;
QGraphicsScene *scene;
//显示各种坐标
QLabel *labViewCord; //视图
QLabel *labSceneCord; //场景
QLabel *labItemCord; //图元
QLabel *labItemInfo;
QPoint actPoint;
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void initview();
void initSlots();
void wheelEvent(QWheelEvent *event); //滑轮
private slots:
void onMouseMovePoint(QPoint ponit); //接收鼠标移动传过来的坐标槽函数
void onMouseClicked(QPoint point); //接收鼠标点击传过来的坐标槽函数
void onMouseRightClicked(QPoint point); //接收鼠标右击传过来的坐标槽函数
void actionTrigger(QAction *act); //菜单槽函数
void onMouseDoubleClick(QPoint point); //接收鼠标双击传过来的坐标槽函数
void onKeyPress(QKeyEvent *event); //接收按键传过来的按键槽函数
//画图的槽函数
void drawPressLine(QPoint point);
void drawReleaseLine(QPoint point);
void onDrawPressRecdangle(QPoint point);
void onDrawReleaseRecdangle(QPoint point);
void drawPressTriangle(QPoint point);
void drawReleaseTriangle(QPoint point);
void drawPressEllipse(QPoint point);
void drawReleaseEllipse(QPoint point);
//各种转到槽
void on_rectangleButton_clicked();
void on_ellipseButton_clicked();
void on_circularButton_clicked();
void on_triangleButton_clicked();
void on_lineButton_clicked();
void on_textButton_clicked();
void on_enlargeButton_clicked();
void on_narrowButton_clicked();
void on_leftButton_clicked();
void on_rightButton_clicked();
void on_frontButton_clicked();
void on_afterButton_clicked();
void on_deleteButton_clicked();
void on_conbButton_clicked();
void on_disperseButton_clicked();
void on_recoveryButton_clicked();
void on_pictrueButton_clicked();
void on_pixmapButton_clicked();
void on_stop_clicked();
void on_run_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QGraphicsRectItem>
#include <QInputDialog>
#include <QColorDialog>
#include <QFontDialog>
#include <QTime>
#include <QMenu>
#include <QColor>
#include <QPixmap>
#include <QKeyEvent>
#include <QFileDialog>
#include <QDebug>
template<class T>
void setBrushColor(T *item)
{
//关于更改方块的颜色的模板函数
QColor color = item->brush().color();
color = QColorDialog::getColor(color,NULL,"选择填充颜色");
if(color.isValid()){ //如果存在与此键关联的缓存像素映射,则返回true。否则,如果pixmap被刷新,密钥将不再有效。
item->setBrush(QBrush(color));
}
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
initview();//美化界面
labViewCord = new QLabel("View 坐标:");
labViewCord->setMinimumWidth(150); //设置最小宽度
ui->statusBar->addWidget(labViewCord);//QStatusBar类提供了一个适合显示状态信息的水平条。
labSceneCord= new QLabel("Scene 坐标:");
labSceneCord->setMinimumWidth(150);
ui->statusBar->addWidget(labSceneCord);
labItemCord = new QLabel("Item 坐标:");
labItemCord->setMinimumWidth(150);
ui->statusBar->addWidget(labItemCord);
labItemInfo = new QLabel("ItemInfo: ");
labItemInfo->setMinimumWidth(200);
ui->statusBar->addWidget(labItemInfo);
scene = new QGraphicsScene(-300, -200, 600, 200);//创建一个场景
ui->graphicsView->setScene(scene); //与view关联
ui->graphicsView->setCursor(Qt::CrossCursor);//设置鼠标,十字光标,通常用于帮助用户准确选择屏幕上的点。
ui->graphicsView->setMouseTracking(true);//启用了鼠标跟踪,即使没有按下按钮,小部件也会接收鼠标移动事件。
//此属性保留按住鼠标左键时在场景上拖动鼠标的行为。
ui->graphicsView->setDragMode(QGraphicsView::RubberBandDrag);//将出现一条橡皮筋。拖动鼠标将设置橡皮筋几何体,并选择橡皮筋覆盖的所有项目
// this->setCentralWidget(ui->graphicsView); //将给定的小部件设置为主窗口的中心小部件。
initSlots(); //信号与槽
qsrand(QTime::currentTime().second()); //关于线程的一个函数
}
void MainWindow::initview()
{
//保存图片
ui->pictrueButton->setToolTip(QString("保存图片"));
ui->pictrueButton->setIcon(QIcon(":/pictrue/save.png"));
//放大
ui->enlargeButton->setToolTip(QString("放大"));
ui->enlargeButton->setIcon(QIcon(":/pictrue/enlarge.png"));
//缩小
ui->narrowButton->setToolTip(QString("缩小"));
ui->narrowButton->setIcon(QIcon(":/pictrue/narrow.png"));
//左右转
ui->leftButton->setToolTip(QString("左转"));
ui->leftButton->setIcon(QIcon(":/pictrue/rightRotation.png"));
ui->rightButton->setToolTip(QString("右转"));
ui->rightButton->setIcon(QIcon(":/pictrue/leftRotation.png"));
//前面置
ui->frontButton->setToolTip(QString("前置"));
ui->frontButton->setIcon(QIcon(":/pictrue/524.bmp"));
ui->afterButton->setToolTip(QString("后置"));
ui->afterButton->setIcon(QIcon(":/pictrue/522.bmp"));
//恢复
ui->recoveryButton->setToolTip(QString("恢复"));
ui->recoveryButton->setIcon(QIcon(":/pictrue/toFront.png"));
//组合
ui->conbButton->setToolTip(QString("组合"));
ui->conbButton->setIcon(QIcon(":/pictrue/con.png"));
//打散
ui->disperseButton->setToolTip(QString("打散"));
ui->disperseButton->setIcon(QIcon(":/pictrue/dis.png"));
//删除
ui->deleteButton->setToolTip(QString("删除"));
ui->deleteButton->setIcon(QIcon(":/pictrue/108.bmp"));
//图形
ui->circularButton->setIcon(QIcon(":/pictrue/iage/cir.png"));
ui->circularButton->setToolTip(QString("圆形"));
ui->ellipseButton->setIcon(QIcon(":/pictrue/iage/ell1.png"));
ui->ellipseButton->setToolTip(QString("椭圆"));
ui->lineButton->setIcon(QIcon(":/pictrue/iage/line1.png"));
ui->lineButton->setToolTip(QString("直线"));
ui->rectangleButton->setIcon(QIcon(":/pictrue/iage/rec1.png"));
ui->rectangleButton->setToolTip(QString("矩形"));
ui->textButton->setIcon(QIcon(":/pictrue/iage/text.bmp"));
ui->textButton->setToolTip(QString("添加文本"));
ui->triangleButton->setIcon(QIcon(":/pictrue/iage/tri1.png"));
ui->triangleButton->setToolTip(QString("三角形"));
ui->pixmapButton->setIcon(QIcon(":/pictrue/iage/K1.png"));
ui->pixmapButton->setToolTip(QString("添加图片"));
}
void MainWindow::initSlots() //各种事件的信号与槽
{
connect(ui->graphicsView, SIGNAL(mouseClicked(QPoint)), this, SLOT(onMouseClicked(QPoint)));
connect(ui->graphicsView, SIGNAL(mouseRightClicked(QPoint)), this, SLOT(onMouseRightClicked(QPoint)));
connect(ui->graphicsView, SIGNAL(mouseDoubleClick(QPoint)), this, SLOT(onMouseDoubleClick(QPoint)));
connect(ui->graphicsView, SIGNAL(mouseMovePoint(QPoint)), this, SLOT(onMouseMovePoint(QPoint)));
connect(ui->graphicsView, SIGNAL(keyPress(QKeyEvent*)), this, SLOT(onKeyPress(QKeyEvent*)));
connect(ui->preser, SIGNAL(triggered(bool)), this, SLOT(on_pictrueButton_clicked()));
connect(ui->out, SIGNAL(triggered(bool)), this, SLOT(close()));
}
void MainWindow::wheelEvent(QWheelEvent *event) //鼠标滑轮事件
{
if(event->delta() > 0){
on_enlargeButton_clicked();
}else{
on_narrowButton_clicked();
}
}
void MainWindow::onMouseMovePoint(QPoint ponit)//鼠标移动事件,ponit表示view的坐标
{
labViewCord->setText(QString::asprintf("View 坐标:%d,%d", ponit.x(), ponit.y()));
QPointF pointScene = ui->graphicsView->mapToScene(ponit); //转换到Scene坐标
labSceneCord->setText(QString::asprintf("Scene 坐标:%.0f,%.0f", pointScene.x(),pointScene.y()));
}
void MainWindow::onMouseClicked(QPoint point)//鼠标左击事件
{
QPointF pointScene = ui->graphicsView->mapToScene(point); //转换到Scene坐标
QGraphicsItem *item = NULL;
item = scene->itemAt(pointScene, ui->graphicsView->transform()); //获取光标下的绘图项
if(item != NULL)
{
QPointF pointItem = item->mapFromScene(pointScene); //转换为绘图项的局部坐标
labItemCord->setText(QString::asprintf("Item 坐标:%.0f,%.0f", pointItem.x(), pointItem.y()));
labItemInfo->setText(item->data(ItemDesciption).toString()+", ItemId="+item->data(ItemId).toString());
}
}
void MainWindow::onMouseRightClicked(QPoint point) //鼠标右击出菜单
{
actPoint = point;
QPointF pointScene = ui->graphicsView->mapToScene(point); //转换到scene坐标
QGraphicsItem *item = NULL;
item = scene->itemAt(pointScene, ui->graphicsView->transform()); //获取光标下的绘图项
if(item == NULL) //没有绘图项
{
return;
}
QMenu *menu = new QMenu(this);
menu->addAction(QString("放大"));
menu->addAction(QString("缩小"));
menu->addAction(QString("左转"));
menu->addAction(QString("右转"));
menu->addAction(QString("前置"));
menu->addAction(QString("后置"));
menu->addAction(QString("组合"));
menu->addAction(QString("散开"));
menu->addAction(QString("删除"));
connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(actionTrigger(QAction*)));
menu->exec(QCursor::pos());
}
void MainWindow::actionTrigger(QAction *act)
{
if(act->text() == "放大"){
on_enlargeButton_clicked();
}else if(act->text() == "缩小"){
on_narrowButton_clicked();
}else if(act->text() == "左转"){
on_leftButton_clicked();
}else if(act->text() == "右转"){
on_rightButton_clicked();
}else if(act->text() == "前置"){
on_frontButton_clicked();
}else if(act->text() == "后置"){
on_afterButton_clicked();
}else if(act->text() == "组合"){
on_conbButton_clicked();
}else if(act->text() == "散开"){
on_disperseButton_clicked();
}else if(act->text() == "删除"){
on_deleteButton_clicked();
}
}
void MainWindow::onMouseDoubleClick(QPoint point)//鼠标双击事件,调用相应的对话框,设置填充颜色、字体
{
QPointF pointScene = ui->graphicsView->mapToScene(point);//转换到scene的坐标
QGraphicsItem *item = NULL;
item = scene->itemAt(pointScene, ui->graphicsView->transform()); //获取光标下的绘图项
if(item == NULL) //没有绘图项
{
return;
}
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()) //如果颜色有效,则返回true;否则返回false。
{
pen.setColor(color);
theItem->setPen(pen);
}
break;
}
case QGraphicsTextItem::Type: //文字,设置字体
{
QGraphicsTextItem *theItem = qgraphicsitem_cast<QGraphicsTextItem*>(item);
QFont font = theItem->font(); //QFont类指定用于绘制文本的字体。
bool ok = false;
font = QFontDialog::getFont(&ok, font, this, "设置字体");
if(ok)
{
theItem->setFont(font);
}
break;
}
}
}
void MainWindow::onKeyPress(QKeyEvent *event)
{
//按键事件
if(scene->selectedItems().count()!=1)//没有选中的绘图项,或选中的多于1个
{
return;
}
QGraphicsItem *item = scene->selectedItems().at(0);
if(event->key() == Qt::Key_Delete){//删除
scene->removeItem(item);
} else if(event->key() == Qt::Key_Space){ //顺时针旋转
item->setRotation(30+item->rotation());//设置围绕Z轴的顺时针旋转角度(以度为单位)。默认值为0
} else if(event->key() == Qt::Key_PageUp){ //放大
item->setScale(0.1+item->scale()); //设置项目的比例因子。默认比例因子为1.0(即,项目未缩放)
} else if(event->key() == Qt::Key_PageDown){ //缩小
item->setScale(-0.1+item->scale());
} else if(event->key() == Qt::Key_Left) { //左移
item->setX(-1+item->x());
} else if(event->key() == Qt::Key_Right){ //右移
item->setX(1+item->x());
} else if(event->key() == Qt::Key_Up){ //上移
item->setY(1+item->y());
} else if(event->key() == Qt::Key_Down){ //下移
item->setY(-1+item->y());
}
}
void MainWindow::drawPressLine(QPoint point)
{
qDebug() << point.x() << point.y();
linePoint = point;
}
void MainWindow::drawReleaseLine(QPoint point) //画直线
{
qDebug() << "画直线";
QGraphicsLineItem *item = new QGraphicsLineItem(0,0,linePoint.x()-point.x(),linePoint.y()-point.y());
item->setFlags(QGraphicsItem::ItemIsMovable
| QGraphicsItem::ItemIsSelectable
| QGraphicsItem::ItemIsFocusable);
QPen pen(Qt::red);
pen.setWidth(3);
item->setPen(pen);
item->setZValue(++frontZ);
QPointF pointScene=ui->graphicsView->mapToScene(point); //转换到Scene坐标
item->setPos(pointScene.x(), pointScene.y());
item->setData(ItemId,++seqNum);
item->setData(ItemDesciption,"直线");
scene->addItem(item);
scene->clearSelection();
item->setSelected(true);
}
void MainWindow::onDrawPressRecdangle(QPoint point)
{
linePoint = point;
}
void MainWindow::onDrawReleaseRecdangle(QPoint point) //画矩形
{
QGraphicsRectItem *item = new QGraphicsRectItem(-abs(linePoint.x()-point.x())/2, -abs(linePoint.y()-point.y())/2, abs(linePoint.x()-point.x()), abs(linePoint.y()-point.y()));//x,y为左上角的图元局部坐标,图元中心为0,0
item->setBrush(QBrush(Qt::yellow)); //设置初始填充颜色
QPointF oldpoint=ui->graphicsView->mapToScene(linePoint); //转换到Scene坐标
QPointF newpoint=ui->graphicsView->mapToScene(point); //转换到Scene坐标
item->setPos((newpoint.x()-oldpoint.x())/2+oldpoint.x(),(newpoint.y()-oldpoint.y())/2+oldpoint.y()); //设置初始坐标
item->setFlags(QGraphicsItem::ItemIsMovable
| QGraphicsItem::ItemIsSelectable
| QGraphicsItem::ItemIsFocusable); //设置图形项的属性,例如:可选择、可移动
item->setZValue(++frontZ);//将项目的Z值设置为Z。Z值决定同级(相邻)项目的堆叠顺序。Z值较高的同级项将始终绘制在Z值较低的另一个同级项的顶部。
//自定义数据
item->setData(ItemId, ++seqNum);
item->setData(ItemDesciption, "矩形");
scene->addItem(item);
// scene->clearSelection(); // 清除当前选择
item->setSelected(true); //初始选择该项目
}
void MainWindow::drawPressTriangle(QPoint point)
{
linePoint = point;
}
void MainWindow::drawReleaseTriangle(QPoint point) //画三角形
{
QGraphicsPolygonItem *item = new QGraphicsPolygonItem;
QPolygonF points; //QPolygonF类使用浮点精度提供点向量。
points.append(QPointF(0,0)); //QPointF类使用浮点精度定义平面中的点。
points.append(QPointF(-((linePoint.x()-point.x())/2),(linePoint.y()-point.y())));
points.append(QPointF((linePoint.x()-point.x())/2,linePoint.y()-point.y()));
item->setPolygon(points);
QPointF pointScene=ui->graphicsView->mapToScene(point); //转换到Scene坐标
item->setPos(pointScene.x()-(point.x()-linePoint.x())/2, pointScene.y());
item->setFlags(QGraphicsItem::ItemIsMovable
| QGraphicsItem::ItemIsSelectable
| QGraphicsItem::ItemIsFocusable);
item->setBrush(QBrush(Qt::magenta));
item->setZValue(++frontZ);
item->setData(ItemId, ++seqNum);
item->setData(ItemDesciption, "三角形");
scene->addItem(item);
scene->clearSelection();
item->setSelected(true);
}
void MainWindow::drawPressEllipse(QPoint point)
{
linePoint = point;
}
void MainWindow::drawReleaseEllipse(QPoint point) //画椭圆
{
QGraphicsEllipseItem *item = new QGraphicsEllipseItem(0, 0, linePoint.x()-point.x(), linePoint.y()-point.y());
item->setFlags(QGraphicsItem::ItemIsMovable
| QGraphicsItem::ItemIsSelectable
| QGraphicsItem::ItemIsFocusable);
item->setBrush(QBrush(Qt::blue));
item->setZValue(++frontZ);
QPointF pointScene=ui->graphicsView->mapToScene(point); //转换到Scene坐标
item->setPos(pointScene.x(), pointScene.y());
item->setData(ItemId, ++seqNum);
item->setData(ItemDesciption, "椭圆");
scene->addItem(item);
scene->clearSelection();
item->setSelected(true);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_rectangleButton_clicked() //添加矩形
{
if(isrectangle){
connect(ui->graphicsView, SIGNAL(mouseClicked(QPoint)), this, SLOT(onDrawPressRecdangle(QPoint)));
connect(ui->graphicsView, SIGNAL(mouseRelease(QPoint)), this, SLOT(onDrawReleaseRecdangle(QPoint)));
ui->rectangleButton->setIcon(QIcon(":/pictrue/iage/rec.png"));
isrectangle = false;
}else{
ui->graphicsView->disconnect(ui->graphicsView, SIGNAL(mouseClicked(QPoint)), this, SLOT(onDrawPressRecdangle(QPoint)));
ui->graphicsView->disconnect(ui->graphicsView, SIGNAL(mouseRelease(QPoint)), this, SLOT(onDrawReleaseRecdangle(QPoint)));
ui->rectangleButton->setIcon(QIcon(":/pictrue/iage/rec1.png"));
isrectangle = true;
}
qDebug() << isrectangle;
}
void MainWindow::on_ellipseButton_clicked() //添加椭圆
{
if(isEllipse){
connect(ui->graphicsView, SIGNAL(mouseClicked(QPoint)), this, SLOT(drawPressEllipse(QPoint)));
connect(ui->graphicsView, SIGNAL(mouseRelease(QPoint)), this, SLOT(drawReleaseEllipse(QPoint)));
ui->ellipseButton->setIcon(QIcon(":/pictrue/iage/ell.png"));
isEllipse = false;
}else{
ui->graphicsView->disconnect(ui->graphicsView, SIGNAL(mouseClicked(QPoint)), this, SLOT(drawPressEllipse(QPoint)));
ui->graphicsView->disconnect(ui->graphicsView, SIGNAL(mouseRelease(QPoint)), this, SLOT(drawReleaseEllipse(QPoint)));
ui->ellipseButton->setIcon(QIcon(":/pictrue/iage/ell1.png"));
isEllipse = true;
}
}
void MainWindow::on_circularButton_clicked() //添加圆形
{
QGraphicsEllipseItem *item = new QGraphicsEllipseItem(-50, -50, 100, 100);
item->setFlags(QGraphicsItem::ItemIsMovable
| QGraphicsItem::ItemIsSelectable
| QGraphicsItem::ItemIsFocusable);
item->setBrush(QBrush(Qt::cyan)); //青色
item->setZValue(++frontZ);
item->setPos(-50+qrand()%100, -50+(qrand()%100));
item->setData(ItemId, ++seqNum);
item->setData(ItemDesciption, "圆形");
scene->addItem(item);
scene->clearSelection();
item->setSelected(true);
}
void MainWindow::on_triangleButton_clicked() //添加三角形
{
if(isTriangle){
connect(ui->graphicsView, SIGNAL(mouseClicked(QPoint)), this, SLOT(drawPressTriangle(QPoint)));
connect(ui->graphicsView, SIGNAL(mouseRelease(QPoint)), this, SLOT(drawReleaseTriangle(QPoint)));
ui->triangleButton->setIcon(QIcon(":/pictrue/iage/tri.png"));
isTriangle = false;
}else{
ui->graphicsView->disconnect(ui->graphicsView, SIGNAL(mouseClicked(QPoint)), this, SLOT(drawPressTriangle(QPoint)));
ui->graphicsView->disconnect(ui->graphicsView, SIGNAL(mouseRelease(QPoint)), this, SLOT(drawReleaseTriangle(QPoint)));
ui->triangleButton->setIcon(QIcon(":/pictrue/iage/tri1.png"));
isTriangle = true;
}
}
void MainWindow::on_lineButton_clicked() //添加直线
{
if(isline){
connect(ui->graphicsView, SIGNAL(mouseClicked(QPoint)), this, SLOT(drawPressLine(QPoint)));
connect(ui->graphicsView, SIGNAL(mouseRelease(QPoint)), this, SLOT(drawReleaseLine(QPoint)));
ui->lineButton->setIcon(QIcon(":/pictrue/iage/line.BMP"));
isline = false;
}else{
ui->graphicsView->disconnect(ui->graphicsView, SIGNAL(mouseClicked(QPoint)), this, SLOT(drawPressLine(QPoint)));
ui->graphicsView->disconnect(ui->graphicsView, SIGNAL(mouseRelease(QPoint)), this, SLOT(drawReleaseLine(QPoint)));
ui->lineButton->setIcon(QIcon(":/pictrue/iage/line1.png"));
isline = true;
}
qDebug() << isline;
}
void MainWindow::on_textButton_clicked() //添加文字
{
QString str = QInputDialog::getText(this, "输入文字", "请输入文字");
if(str.isEmpty())
{
return;
}
QGraphicsTextItem *item = new QGraphicsTextItem(str);
QFont font = this->font();
font.setPointSize(20);
font.setBold(true);
item->setFont(font);
item->setFlags(QGraphicsItem::ItemIsMovable
| QGraphicsItem::ItemIsSelectable
| QGraphicsItem::ItemIsFocusable);
item->setPos(-50+(qrand()%100), -50+(qrand()%100));
item->setZValue(++frontZ);
item->setData(ItemId, ++seqNum);
item->setData(ItemDesciption, "文字");
scene->addItem(item);
scene->clearSelection();
item->setSelected(true);
}
void MainWindow::on_enlargeButton_clicked() //放大
{
int cnt = scene->selectedItems().count();
if(cnt == 1){
QGraphicsItem *item;
item = scene->selectedItems().at(0);
item->setScale(0.1+item->scale()); // 比例因子
}else{
ui->graphicsView->scale(1.1,1.1); //按(sx,sy)缩放当前视图变换,正常比例为1,1。
}
}
void MainWindow::on_narrowButton_clicked() //缩小
{
int cnt = scene->selectedItems().count();
if(cnt == 1){
QGraphicsItem *item;
item = scene->selectedItems().at(0);
item->setScale(-0.1+item->scale());
}else{
ui->graphicsView->scale(0.9,0.9); //正常比例为1,1
}
}
void MainWindow::on_leftButton_clicked() //左转
{
int cnt = scene->selectedItems().count();
if(cnt == 1){
QGraphicsItem *item =scene->selectedItems().at(0);
item->setRotation(-30+item->rotation());
}else{
ui->graphicsView->rotate(-30); //rotate:顺时针旋转当前视图变换角度。
}
}
void MainWindow::on_rightButton_clicked() //右转
{
int cnt = scene->selectedItems().count(); //返回所有当前选定项目的列表
if(cnt == 1){
QGraphicsItem *item = scene->selectedItems().at(0);
item->setRotation(30+item->rotation());
}else{
ui->graphicsView->rotate(30);
}
}
void MainWindow::on_frontButton_clicked() //前置
{
int cnt = scene->selectedItems().count();
if(cnt > 0){
//只处理第一个选中项
QGraphicsItem *item = scene->selectedItems().at(0);
item->setZValue(++frontZ);
}
}
void MainWindow::on_afterButton_clicked() //后置
{
int cnt = scene->selectedItems().count();
if(cnt > 0){
QGraphicsItem *item = scene->selectedItems().at(0);
item->setZValue(--backZ);
}
}
void MainWindow::on_deleteButton_clicked() //删除
{
int cnt = scene->selectedItems().count();
if(cnt > 0){
int i = 0;
for(i=0; i < cnt; i++){
QGraphicsItem *item = scene->selectedItems().at(0);
scene->removeItem(item); //删除绘图项
}
}
}
void MainWindow::on_conbButton_clicked() //组合
{
int cnt = scene->selectedItems().count();
if(cnt > 1){
QGraphicsItemGroup *group = new QGraphicsItemGroup;//QGraphicsItemGroup类提供了一个容器,将一组项视为单个项。
// QGraphicsItemGroup是一种特殊类型的复合项,它将自身及其所有子项视为一个项(即,所有子项的所有事件和几何图形都合并在一起)。
scene->addItem(group);
for(int i=0; i<cnt; i++){
QGraphicsItem *item = scene->selectedItems().at(0);
item->setSelected(false);//清除虚线
item->clearFocus(); //
group->addToGroup(item); //添加到组合去
}
group->setFlags(QGraphicsItem::ItemIsMovable
| QGraphicsItem::ItemIsSelectable
| QGraphicsItem::ItemIsFocusable);
group->setZValue(++frontZ);
scene->clearSelection();
group->setSelected(true);
}
}
void MainWindow::on_disperseButton_clicked() //打散
{
int cnt = scene->selectedItems().count();
if(cnt == 1){
QGraphicsItemGroup *group;
group=(QGraphicsItemGroup*)scene->selectedItems().at(0);
scene->destroyItemGroup(group);
//将组中的所有项目重设为组的父项目,然后从场景中移除组,最后将其删除。项目的位置和变换从组映射到组的父对象。
}
}
void MainWindow::on_recoveryButton_clicked() //视图恢复
{
int cnt = scene->selectedItems().count();
if(cnt == 1){
QGraphicsItem *item = scene->selectedItems().at(0);
item->resetTransform();
}else{
ui->graphicsView->resetTransform();//将视图转换重置为标识矩阵。
}
}
void MainWindow::on_pictrueButton_clicked() //保存图片
{
QPixmap map = ui->graphicsView->grab();
QString filename;
filename = QFileDialog::getSaveFileName(this, tr("保存图片"), "", tr("Image Files(*.png *.jpg *.bmp)"));
if(!filename.isNull()){
QFile *file = new QFile(filename);
file->open(QIODevice::ReadWrite);
map.save(file);
file->close();
}
}
void MainWindow::on_pixmapButton_clicked() //添加图片
{
QGraphicsPixmapItem *pixmap = scene->addPixmap(QPixmap(QFileDialog::getOpenFileName(this, "Open", "./", "*.png")));
pixmap->setPos(0,0);
pixmap->setZValue(++frontZ);
pixmap->setFlags(QGraphicsItem::ItemIsMovable
| QGraphicsItem::ItemIsSelectable
| QGraphicsItem::ItemIsFocusable);
pixmap->setData(ItemId, ++seqNum);
pixmap->setData(ItemDesciption, "图片");
scene->addItem(pixmap);
scene->clearSelection();
pixmap->setSelected(true);
}
void MainWindow::on_stop_clicked()
{
int cnt = scene->selectedItems().count();
if(cnt > 0){
int i = 0;
for(i=0; i < cnt; i++){
QGraphicsItem *item = scene->selectedItems().at(i);
item->setFlags(QGraphicsItem::ItemStopsFocusHandling
| QGraphicsItem::ItemIsSelectable);
}
}
}
void MainWindow::on_run_clicked()
{
int cnt = scene->selectedItems().count();
if(cnt > 0){
int i = 0;
for(i=0; i < cnt; i++){
QGraphicsItem *item = scene->selectedItems().at(i);
item->setFlags(QGraphicsItem::ItemIsMovable
| QGraphicsItem::ItemIsSelectable
| QGraphicsItem::ItemIsFocusable);
}
}
}
下面是对视图进行重写,在ui界面对控件进行提升
mygraphicsview.h
#ifndef MYGRAPHICSVIEW_H
#define MYGRAPHICSVIEW_H
#include <QObject>
#include <QGraphicsView>
class MyGraphicsView : public QGraphicsView
{
Q_OBJECT
public:
MyGraphicsView(QWidget *parent = 0);
QColor BackgroundColor = QColor(53,53,53); //背景颜色
QColor FineGridColor = QColor(0,60,0); //细网格颜色
QColor CoarseGridColor = QColor(120,25,25); //粗网格颜色
protected:
void mouseMoveEvent(QMouseEvent *event); //鼠标移动事件
void mousePressEvent(QMouseEvent *event); //鼠标按下事件
void mouseReleaseEvent(QMouseEvent *event); //鼠标释放事件
void mouseDoubleClickEvent(QMouseEvent *event); //鼠标双击事件
void keyPressEvent(QKeyEvent *event); //键盘按下事件
void drawBackground(QPainter *painter, const QRectF &r); //改变背景颜色
signals:
void mouseMovePoint(QPoint point); //鼠标移动坐标
void mouseClicked(QPoint point); //鼠标左击按下坐标
void mouseRelease(QPoint point); //鼠标释放坐标
void mouseRightClicked(QPoint point);//鼠标右击按下坐标
void mouseDoubleClick(QPoint point); //鼠标双击坐标
void keyPress(QKeyEvent *event); //键盘按下
};
#endif // MYGRAPHICSVIEW_H
mygraphicsview.cpp
#include "mygraphicsview.h"
#include <QMouseEvent>
#include <QPoint>
#include <QRect>
#include <cmath>
MyGraphicsView::MyGraphicsView(QWidget *parent):QGraphicsView(parent)
{
//滚动条隐藏
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
//绘图抗锯齿
setRenderHints(QPainter::Antialiasing);
//设置背景颜色
setBackgroundBrush(BackgroundColor);
}
void MyGraphicsView::mouseMoveEvent(QMouseEvent *event)
{
//鼠标移动事件
QPoint point = event->pos(); //保存鼠标移动的坐标
emit mouseMovePoint(point); //发送信号
QGraphicsView::mouseMoveEvent(event); //使父类的事件不受影响
}
void MyGraphicsView::mousePressEvent(QMouseEvent *event)
{
//鼠标按下事件
if(event->button() == Qt::LeftButton) //判断鼠标按下的是左键
{
QPoint point = event->pos(); //保存View此时的坐标
emit mouseClicked(point); //发送信号
}else if(event->button() == Qt::RightButton){ //判断鼠标按下的是右键
QPoint poind = event->pos();
emit mouseRightClicked(poind);
}
QGraphicsView::mousePressEvent(event);
}
void MyGraphicsView::mouseReleaseEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton) //判断鼠标释放的是左键
{
QPoint point = event->pos(); //保存View此时的坐标
emit mouseRelease(point); //发送信号
}
QGraphicsView::mouseReleaseEvent(event);
}
void MyGraphicsView::mouseDoubleClickEvent(QMouseEvent *event)
{
//鼠标双击事件
if(event->button() == Qt::LeftButton)
{
QPoint point = event->pos();//保存View此时的坐标
emit mouseDoubleClick(point); //发送信号
}
QGraphicsView::mouseDoubleClickEvent(event);
}
void MyGraphicsView::keyPressEvent(QKeyEvent *event)
{
emit keyPress(event);
QGraphicsView::keyPressEvent(event);
}
void MyGraphicsView::drawBackground(QPainter *painter, const QRectF &r)
{
QGraphicsView::drawBackground(painter, r);
auto drawGrid = [&](double gridStep){
QRect windowRect = rect();
QPointF tl = mapToScene(windowRect.topLeft());
QPointF br = mapToScene(windowRect.bottomRight());
double left = std::floor(tl.x() / gridStep - 0.5);
double right = std::floor(br.x() / gridStep + 1.0);
double bottom = std::floor(tl.y() / gridStep - 0.5);
double top = std::floor(br.y() / gridStep + 1.0);
//垂直线
for(int xi = int(left); xi <= int(right); ++xi){
QLine line(xi * gridStep, bottom * gridStep, xi * gridStep, top * gridStep);
painter->drawLine(line);
}
//水平线
for(int yi = int(bottom); yi<= int(top); ++yi){
QLine line(left * gridStep, yi * gridStep, right * gridStep, yi * gridStep);
painter->drawLine(line);
}
};
QPen pfine(FineGridColor, 1.0);
painter->setPen(pfine);
drawGrid(15);
QPen p(CoarseGridColor, 1.0);
painter->setPen(p);
drawGrid(150);
}
结尾
这是学习QT之后跟着写的一个小项目,很多地方还有bug,这篇文章只能做一个参考,谢谢!如对你有用,可以点一个小小赞,非常感谢!
注:如有侵权,请联系本人删除此文章。