2025年3月20日 星期四 甲辰(龙)年 月十九 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > Qt

QT 简单画图板

时间:03-17来源:作者:点击数:49

一、简述

QT 简单画图板,基本实现功能:

1、打开图片

2、保存图片

3、铅笔画线

4、直线

5、矩形

6、椭圆

7、文字

8、矩形、椭圆刚画完后可以移动

9、撤回 (Ctrl+z)

10、右键菜单

例子打包:链接: https://pan.baidu.com/s/1VbFRXnKx8V6iFxrO3LxcNA 提取码: 1cf9

二、效果

三、工程结构

打包文件预览:

四、源文件

MyPaint.pro文件

  • QT +=widgets gui
  • SOURCES += \
  • main.cpp \
  • mypaint.cpp
  • HEADERS += \
  • mypaint.h
  • RESOURCES += \
  • images.qrc

mypaint.h文件

  • #ifndef MYPAINT_H
  • #define MYPAINT_H
  • #include <QMainWindow>
  • #include <QPaintEvent>
  • #include <QMouseEvent>
  • #include <QPainter>
  • #include <QVector>
  • #include <QPoint>
  • #include <QToolBar>
  • #include <QAction>
  • #include <QPalette>
  • #include <QColor>
  • #include <QMenu>
  • #include <QFileDialog>
  • #include <QTextEdit>
  • class MyPaint : public QMainWindow
  • {
  • Q_OBJECT
  • public:
  • explicit MyPaint(QWidget *parent = 0);
  • protected:
  • void paintEvent(QPaintEvent *);//重写窗体重绘事件
  • void mousePressEvent(QMouseEvent *);//重写鼠标按下事件
  • void mouseReleaseEvent(QMouseEvent *);//重写鼠标释放事件
  • void mouseMoveEvent(QMouseEvent *);//重写鼠标移动事件
  • void contextMenuEvent(QContextMenuEvent *);//重写菜单事件
  • void keyPressEvent(QKeyEvent *e); //重写按键事件
  • public:
  • private:
  • int _lpress;//左键按下标志
  • int _drag;//拖拽标志
  • int _drawType;//描绘类型
  • QMenu *_Rmenu;//右键菜单
  • int _openflag;//打开图片
  • QPixmap _pixmap;//画布图片
  • QTextEdit *_tEdit;//文本输入框
  • public:
  • QVector<QVector<QPoint> > _lines;//线条集合(一条线条可包含多个线段)
  • QVector<QRect> _rects;//矩形集合
  • QVector<QRect> _ellipse;//椭圆集合
  • QVector<QRect> _line;//直线集合
  • QVector<QString> _text;//文字集合
  • QVector<QPoint> _tpoint;//文字位置集合
  • QVector<int> _shape;//图形类型集合,用于撤回功能
  • QPoint _begin;//鼠标按下坐标、用于最后一个图形移动
  • signals:
  • public slots:
  • void Lines();//铅笔画线
  • void SavePic();//保存图片
  • void Rects();//画矩形
  • void Ellipses();//画椭圆
  • void Line();//画直线
  • void OpenPic();//打开图片
  • void Texts();//文字
  • void AddTexts();//添加文字
  • };
  • #endif // MYPAINT_H

mypaint.cpp文件

  • #include "mypaint.h"
  • #include <QDebug>
  • MyPaint::MyPaint(QWidget *parent) :
  • QMainWindow(parent)
  • {
  • _lpress = false;//初始鼠标左键未按下
  • _drawType = 0;//初始为什么都不画
  • _drag = 0;//默认非拖拽模式
  • _begin = pos();//拖拽的参考坐标,方便计算位移
  • _openflag = 0;//初始不打开图片
  • _tEdit = new QTextEdit(this);//初始化文本输入框
  • _tEdit->hide();//隐藏
  • this->setGeometry(350,200,600,400);//设置窗体大小、位置
  • setMouseTracking(true);//开启鼠标实时追踪,监听鼠标移动事件,默认只有按下时才监听
  • //设置背景黑色
  • //方法一
  • // QPalette palt(this->palette());
  • // palt.setColor(QPalette::Background, Qt::white);
  • // this->setAutoFillBackground(true);
  • // this->setPalette(palt);
  • //方法二
  • this->setStyleSheet("background-color:white;");
  • //创建工具栏
  • QToolBar *tbar = addToolBar(tr("工具栏"));
  • tbar->setMovable(false);//工具栏不可移动
  • tbar->setIconSize(QSize(16, 16));//设置动作图标的尺寸
  • tbar->setStyleSheet("background-color:rgb(199,237,204)");//背景色
  • _Rmenu = new QMenu(this);//创建右键菜单
  • _Rmenu->addAction(tr("保存 \tCtrl+S"), this, SLOT(SavePic()));//添加菜单动作
  • _Rmenu->addAction(tr("退出 \tALT+F4"), this, SLOT(close()));//添加菜单动作
  • _Rmenu->setStyleSheet("background-color:rgb(199,237,204)");//设置背景色
  • QAction *openAction = new QAction(tr("&打开"), this);//打开动作
  • openAction->setIcon(QIcon(":/png/images/open.png"));//图标
  • openAction->setShortcut(QKeySequence(tr("Ctrl+O")));//热键
  • tbar->addAction(openAction);//添加到工具栏
  • QAction *saveAction = new QAction(tr("&保存"), this);//保存动作
  • saveAction->setIcon(QIcon(":/png/images/save.png"));//图标
  • saveAction->setShortcut(QKeySequence(tr("Ctrl+S")));//热键
  • tbar->addAction(saveAction);//添加到工具栏
  • QAction *saveasAction = new QAction(tr("&另存为"), this);//保存动作
  • saveasAction->setIcon(QIcon(":/png/images/saveas.png"));//图标
  • saveasAction->setShortcut(QKeySequence(tr("Ctrl+ALT+S")));//热键
  • tbar->addAction(saveasAction);//添加到工具栏
  • QAction *lineAction = new QAction(tr("&直线"), this);//直线动作
  • lineAction->setIcon(QIcon(":/png/images/line.png"));//图标
  • lineAction->setShortcut(QKeySequence(tr("Ctrl+L")));//热键
  • tbar->addAction(lineAction);//添加到工具栏
  • QAction *linesAction = new QAction(tr("&铅笔"), this);//铅笔动作
  • linesAction->setIcon(QIcon(":/png/images/lines.png"));//图标
  • linesAction->setShortcut(QKeySequence(tr("Ctrl+P")));//热键
  • tbar->addAction(linesAction);//添加到工具栏
  • QAction *rectAction = new QAction(tr("&矩形"), this);//矩形动作
  • rectAction->setIcon(QIcon(":/png/images/rect.png"));//图标
  • rectAction->setShortcut(QKeySequence(tr("Ctrl+R")));//热键
  • tbar->addAction(rectAction);
  • QAction *ellipseAction = new QAction(tr("&椭圆"), this);//椭圆动作
  • ellipseAction->setIcon(QIcon(":/png/images/ellipse.png"));//图标
  • ellipseAction->setShortcut(QKeySequence(tr("Ctrl+E")));//热键
  • tbar->addAction(ellipseAction);
  • QAction *textAction = new QAction(tr("&文字"), this);//文字动作
  • textAction->setIcon(QIcon(":/png/images/texts.png"));//图标
  • textAction->setShortcut(QKeySequence(tr("Ctrl+T")));//热键
  • tbar->addAction(textAction);
  • //连接信号与槽函数
  • connect(linesAction, SIGNAL(triggered()), this, SLOT(Lines()));
  • connect(rectAction, SIGNAL(triggered()), this, SLOT(Rects()));
  • connect(ellipseAction, SIGNAL(triggered()), this, SLOT(Ellipses()));
  • connect(lineAction, SIGNAL(triggered()), this, SLOT(Line()));
  • connect(saveAction, SIGNAL(triggered()), this, SLOT(SavePic()));
  • connect(openAction, SIGNAL(triggered()), this, SLOT(OpenPic()));
  • connect(textAction, SIGNAL(triggered()), this, SLOT(Texts()));
  • connect(_tEdit, SIGNAL(textChanged()), this, SLOT(AddTexts()));
  • }
  • void MyPaint::paintEvent(QPaintEvent *)
  • {
  • if(_openflag == 0)//不是打开图片的,每一次新建一个空白的画布
  • {
  • _pixmap = QPixmap(size());//新建pixmap
  • _pixmap.fill(Qt::white);//背景色填充为白色
  • }
  • QPixmap pix = _pixmap;//以_pixmap作为画布
  • QPainter p(&pix);//将_pixmap作为画布
  • unsigned int i1=0,i2=0,i3=0,i4=0,i5=0;//各种图形的索引
  • for(int c = 0;c<_shape.size();++c)//控制用户当前所绘图形总数
  • {
  • if(_shape.at(c) == 1)//线条
  • {
  • const QVector<QPoint>& line = _lines.at(i1++);//取出一条线条
  • for(int j=0; j<line.size()-1; ++j)//将线条的所有线段描绘出
  • {
  • p.drawLine(line.at(j), line.at(j+1));
  • }
  • }
  • else if(_shape.at(c) == 2)//矩形
  • {
  • p.drawRect(_rects.at(i2++));
  • }
  • else if(_shape.at(c) == 3)//椭圆
  • {
  • p.drawEllipse(_ellipse.at(i3++));
  • }
  • else if(_shape.at(c) == 4)//直线
  • {
  • p.drawLine(_line.at(i4).topLeft(),_line.at(i4).bottomRight());
  • i4++;
  • }
  • else if(_shape.at(c) == 5)//文本
  • {
  • p.drawText(_tpoint.at(i5),_text.at(i5));
  • i5++;
  • }
  • }
  • p.end();
  • p.begin(this);//将当前窗体作为画布
  • p.drawPixmap(0,0, pix);//将pixmap画到窗体
  • }
  • void MyPaint::mousePressEvent(QMouseEvent *e)
  • {
  • if(e->button() == Qt::LeftButton)//当鼠标左键按下
  • {
  • if(_drawType == 1)//线条(铅笔)
  • {
  • _lpress = true;//左键按下标志
  • QVector<QPoint> line;//鼠标按下,新的线条开始
  • _lines.append(line);//将新线条添加到线条集合
  • QVector<QPoint>& lastLine = _lines.last();//拿到新线条
  • lastLine.append(e->pos());//记录鼠标的坐标(新线条的开始坐标)
  • _shape.append(1);
  • }
  • else if(_drawType == 2)//矩形
  • {
  • _lpress = true;//左键按下标志
  • if(!_drag)//非拖拽模式
  • {
  • QRect rect;//鼠标按下,矩形开始
  • _rects.append(rect);//将新矩形添加到矩形集合
  • QRect& lastRect = _rects.last();//拿到新矩形
  • lastRect.setTopLeft(e->pos());//记录鼠标的坐标(新矩形的左上角坐标)
  • _shape.append(2);
  • }
  • else if(_rects.last().contains(e->pos()))//拖拽模式、如果在矩形内按下
  • {
  • _begin = e->pos();//记录拖拽开始的坐标位置,方便计算位移
  • }
  • }
  • else if(_drawType == 3)//椭圆
  • {
  • _lpress = true;//左键按下标志
  • if(!_drag)//非拖拽模式
  • {
  • QRect rect;//鼠标按下,椭圆开始
  • _ellipse.append(rect);//将新椭圆添加到椭圆集合
  • QRect& lastEllipse = _ellipse.last();//拿到新椭圆
  • lastEllipse.setTopLeft(e->pos());//记录鼠标的坐标(新椭圆的左上角坐标)
  • _shape.append(3);
  • }
  • else if(_ellipse.last().contains(e->pos()))//如果在椭圆内按下
  • {
  • _begin = e->pos();//记录拖拽开始的坐标位置
  • }
  • }
  • else if(_drawType == 4)//直线
  • {
  • _lpress = true;//左键按下标志
  • QRect rect;//鼠标按下,直线一端开始
  • _line.append(rect);//将新直线添加到直线集合
  • QRect& lastLine = _line.last();//拿到新直线
  • lastLine.setTopLeft(e->pos());//记录鼠标的坐标(新直线开始一端坐标)
  • _shape.append(4);
  • }
  • else if(_drawType == 5)//文字
  • {
  • update();//触发窗体重绘
  • QPoint p;//鼠标按下,文字开始
  • _tpoint.append(p);//将文字坐标添加到文字位置集合
  • QPoint& lastp = _tpoint.last();//拿到新文字
  • lastp = e->pos();//记录鼠标的坐标
  • _tEdit->setGeometry(lastp.x()-6,lastp.y()-17,90,90);//设置文本框的位置、大小
  • _tEdit->show();//显示文本输入框
  • _text.append("");//添加文本到文本集合
  • _tEdit->clear();//因为全局只有一个,所以使用之前要清空
  • _shape.append(5);
  • }
  • }
  • }
  • void MyPaint::AddTexts()//当输入框文本改变时调用
  • {
  • QString& last = _text.last();//拿到最后一个文本
  • last = _tEdit->toPlainText();//将输入框文本作为文本
  • }
  • void MyPaint::mouseMoveEvent(QMouseEvent *e)
  • {
  • if(_drag && ((_drawType == 2 && _rects.last().contains(e->pos()))
  • || (_drawType == 3 && _ellipse.last().contains(e->pos()) )))
  • {
  • setCursor(Qt::SizeAllCursor);//拖拽模式下,并且在拖拽图形中,将光标形状改为十字
  • }
  • else
  • {
  • setCursor(Qt::ArrowCursor);//恢复原始光标形状
  • _drag = 0;
  • }
  • if(_lpress)
  • {
  • if(_drawType == 1)//铅笔画线
  • {
  • if(_lines.size()<=0) return;//线条集合为空,不画线
  • QVector<QPoint>& lastLine = _lines.last();//最后添加的线条,就是最新画的
  • lastLine.append(e->pos());//记录鼠标的坐标(线条的轨迹)
  • update();//触发窗体重绘
  • }
  • else if(_drawType == 2)
  • {
  • if(_drag == 0)//非拖拽
  • {
  • QRect& lastRect = _rects.last();//拿到新矩形
  • lastRect.setBottomRight(e->pos());//更新矩形的右下角坐标
  • }
  • else//拖拽模式
  • {
  • QRect& lastRect = _rects.last();//拿到最后添加的矩形
  • if(lastRect.contains(e->pos()))//在矩形的内部
  • {
  • int dx = e->pos().x()-_begin.x();//横向移动x
  • int dy = e->pos().y()-_begin.y();//纵向移动y
  • lastRect = lastRect.adjusted(dx,dy,dx,dy);//更新矩形的位置
  • _begin = e->pos();//刷新拖拽点起始坐标
  • }
  • }
  • update();//触发窗体重绘
  • }
  • else if(_drawType == 3)
  • {
  • if(_drag == 0)//非拖拽
  • {
  • QRect& lastEllipse = _ellipse.last();//拿到新椭圆
  • lastEllipse.setBottomRight(e->pos());//更新椭圆的右下角坐标)
  • }
  • else//拖拽
  • {
  • QRect& lastEllipse = _ellipse.last();//拿到最后添加的矩形
  • if(lastEllipse.contains(e->pos()))//在椭圆内部
  • {
  • int dx = e->pos().x()-_begin.x();//横向移动x
  • int dy = e->pos().y()-_begin.y();//纵向移动y
  • lastEllipse = lastEllipse.adjusted(dx,dy,dx,dy);
  • _begin = e->pos();//刷新拖拽点起始坐标
  • }
  • }
  • update();//触发窗体重绘
  • }
  • else if(_drawType == 4)
  • {
  • QRect& lastLine = _line.last();//拿到新直线
  • lastLine.setBottomRight(e->pos());//更新直线另一端)
  • update();//触发窗体重绘
  • }
  • }
  • }
  • void MyPaint::mouseReleaseEvent(QMouseEvent *e)
  • {
  • if(_lpress)
  • {
  • if(_drawType == 1)
  • {
  • QVector<QPoint>& lastLine = _lines.last();//最后添加的线条,就是最新画的
  • lastLine.append(e->pos());//记录线条的结束坐标
  • _lpress = false;//标志左键释放
  • }
  • else if(_drawType == 2)
  • {
  • QRect& lastRect = _rects.last();//拿到新矩形
  • if(!_drag)
  • {
  • lastRect.setBottomRight(e->pos());//不是拖拽时,更新矩形的右下角坐标)
  • //刚画完矩形,将光标设置到新矩形的中心位置,并进入拖拽模式
  • this->cursor().setPos(this->cursor().pos().x()-lastRect.width()/2,this->cursor().pos().y()-lastRect.height()/2);
  • _drag = 1;
  • }
  • _lpress = false;
  • }
  • else if(_drawType == 3)
  • {
  • QRect& lastEllipse = _ellipse.last();//拿到新椭圆
  • if(!_drag)
  • {
  • lastEllipse.setBottomRight(e->pos());//不是拖拽时,更新椭圆的右下角坐标)
  • //刚画完椭圆,将光标设置到新椭圆的中心位置,并进入拖拽模式
  • this->cursor().setPos(this->cursor().pos().x()-lastEllipse.width()/2,this->cursor().pos().y()-lastEllipse.height()/2);
  • _drag = 1;
  • }
  • _lpress = false;
  • }
  • else if(_drawType == 4)
  • {
  • QRect& lastLine = _line.last();//拿到新矩形
  • lastLine.setBottomRight(e->pos());//更新矩形的右下角坐标)
  • _lpress = false;
  • }
  • }
  • }
  • void MyPaint::Lines()
  • {
  • _drawType = 1;//铅笔
  • _tEdit->hide();//文本框隐藏
  • }
  • void MyPaint::Line()
  • {
  • _drawType = 4;//直线
  • _tEdit->hide();
  • }
  • void MyPaint::Rects()
  • {
  • _drawType = 2;//矩形
  • _tEdit->hide();
  • }
  • void MyPaint::Ellipses()
  • {
  • _drawType = 3;//椭圆
  • _tEdit->hide();
  • }
  • void MyPaint::Texts()
  • {
  • _drawType = 5;//文字
  • }
  • void MyPaint::SavePic()
  • {
  • //弹出文件保存对话框
  • QString fileName = QFileDialog::getSaveFileName(this, tr("保存"), "new.jpg", "Image (*.jpg *.png *.bmp)");
  • if (fileName.length() > 0)
  • {
  • _tEdit->hide();//防止文本输入框显示时,将文本框保存到图片
  • QPixmap pixmap(size());//新建窗体大小的pixmap
  • QPainter painter(&pixmap);//将pixmap作为画布
  • painter.fillRect(QRect(0, 0, size().width(), size().height()), Qt::white);//设置绘画区域、画布颜色
  • this->render(&painter);//将窗体渲染到painter,再由painter画到画布
  • pixmap.copy(QRect(0,30,size().width(),size().height()-30)).save(fileName);//不包含工具栏
  • }
  • }
  • void MyPaint::OpenPic()
  • {
  • //弹出文件打开对话框
  • QString picPath = QFileDialog::getOpenFileName(this,tr("打开"),"","Image Files(*.jpg *.png)");
  • if(!picPath.isEmpty())//用户选择了文件
  • {
  • QPixmap pix;
  • pix.load(picPath);//加载图片
  • QPainter p(&_pixmap);
  • p.drawPixmap(0,30,pix);//添加工具栏的空间
  • _openflag = 1;//设置文件打开标志
  • update();//触发窗体重绘,将图片画到窗体
  • }
  • }
  • void MyPaint::contextMenuEvent(QContextMenuEvent *) //右键菜单事件
  • {
  • _Rmenu->exec(cursor().pos());//在光标位置弹出菜单
  • }
  • void MyPaint::keyPressEvent(QKeyEvent *e) //按键事件
  • {
  • //Ctrl+Z撤销
  • if (e->key() == Qt::Key_Z && e->modifiers() == Qt::ControlModifier)
  • {
  • if(_shape.size()>0)
  • {
  • switch(_shape.last())
  • {
  • case 1: _lines.pop_back();
  • break;
  • case 2: _rects.pop_back();
  • break;
  • case 3: _ellipse.pop_back();
  • break;
  • case 4: _line.pop_back();
  • break;
  • }
  • _shape.pop_back();
  • _drag = 0;//设置为非拖拽模式
  • update();
  • }
  • }
  • else if (e->key() == Qt::Key_S && e->modifiers() == Qt::ControlModifier)//保存
  • {
  • SavePic();//Ctrl+S保存
  • }
  • }

main.cpp文件

  • #include <QApplication>
  • #include "mypaint.h"
  • int main(int argc,char* argv[])
  • {
  • QApplication app(argc,argv);
  • MyPaint *w = new MyPaint();
  • w->setWindowIcon(QIcon(":/png/images/1.png"));
  • w->show();
  • return app.exec();
  • }

五、添加资源

1、右键项目-》新建项目

2、选择Qt-》Qt资源文件-》选择

3、填写名称。。。。

4、添加前缀

5、添加文件

六、小结

1、在安装好QtCreate环境下,导入项目:

或者打开QtCreate再打开。

2、单独将生成的exe拷贝出来运行,出现以下问题:

如果出现类似"因为计算机丢失Qt5xxx.dll"的问题,是因为这个exe是动态编译的,库文件是动态链接的。运行时在系统环境时找不到库文件。

解决方式1:将所需要的库文件拷贝到exe的同级目录。

解决方式2:将库文件的相关路径添加到环境变量。

首先找到需要的库文件的路径,通常是在安装目录下的bin目录:我的安转路径是D:\QtCreate

库路径是:D:\QtCreate\5.7\mingw53_32\bin

将库的路径D:\QtCreate\5.7\mingw53_32\bin添加到环境变量中:

对着"计算机"右键--》"高级系统设置"--》"环境变量"--》在系统变量找到“Path”--》“编辑”--》将库路径添加进去

以英文状态下的分号 与其它内容分隔。如果例子中是在最前面添加库路径,所以在库的路径后面添加分号。

如果在最后面添加,就要在库路径的前面添加分号。如果在中间添加,需要在库路径的前后添加分号。

注:静态编译就将需要到的库文件等都编译成为exe的一部分,这种exe体积变大,但是拷贝到没有QT环境的计算机 可以直接运行。

6.3 多边形图形填充颜色

  • //多边形图形路径
  • QPainterPath rectPath;
  • rectPath.moveTo(20.0, 50.0);
  • rectPath.lineTo(80.0, 50.0);
  • rectPath.lineTo(150.0, 100.0);
  • rectPath.lineTo(80.0, 200.0);
  • rectPath.lineTo(20.0, 200.0);
  • rectPath.closeSubpath();
  • //填充颜色
  • p.setPen(QPen(Qt::blue, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
  • QLinearGradient gradient(0, 0, 0, 100);
  • //渐变效果
  • gradient.setColorAt(0.0, Qt::blue);
  • gradient.setColorAt(1.0, Qt::red);
  • p.setBrush(gradient);
  • //画图
  • p.drawPath(rectPath);
  • //注:p是QPainter,画图在paintEvent(QPaintEvent *)函数中

====================以下 回复 网友兄弟=====================

有MSVC编译器的环境下安装 MSVC版本的qt,成功导入项目并运行。

qt下载:http://download.qt.io/archive/qt/5.5/5.5.0/

vs版本:

==================以下回复 网友兄弟======

我测试了一下密码是对的,

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门