学习笔记 QT之Graphic图形编辑器

注:本人学习阶段,仅供参考。如有错误,请指正,谢谢!

一、简单介绍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,这篇文章只能做一个参考,谢谢!如对你有用,可以点一个小小赞,非常感谢!

       注:如有侵权,请联系本人删除此文章。

  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值