引言
实现可以选择线型,线宽,颜色,是否填充图形来绘制各种常见的图形,同时可以选择矩形区域来实现截图。
效果
绘图的效果如上,截图的效果:
实现
项目使用的qt5.13.2,编译器为MSVC2017_64bit,该项目是基于基类QWidget创建的应用程序,创建时带有ui文件。下面是整个项目的代码。
main.cpp
#include "widget.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QPen>
#include <QStack>
#include <QPixmap>
#include "screenshot.h"/********************************************======功能描述:=======1.绘制曲线,2.绘制直线,3.绘制矩形,4.绘制椭圆,5.绘制三角形,6.绘制平行四边形,7.绘制菱形,8.绘制梯形,9.可以选择绘制图形的颜色,10.在选择颜色后可以设置是否填充,11.可以选择线型,12.可以选择线宽,13.撤销,14.剪裁保存。不足:曲线含有明显的折点,不平滑。心得:1.实时画直线只需要记住起点,然后更新终点,来画线;2.保存每条线的颜色时只保存一次,不能在绘制的时候保存,必须在鼠标释放时保存,曲线除外,曲线从鼠标点击后一直开始绘制,保存曲线绘制的颜色,必须在鼠标点击后保存;3.图形的填充也需在每个图形绘制的时候保存该图形是否填充,直线和曲线不需要设置填充;4.注意不能再改类中直接创建截图的蒙层,也就是说截图功能得单独实现,之所以这么做的原因:创建的蒙层存在与应用程序的窗口,而不是整个桌面,与此同时图片会嵌入到应用程序的窗口中,不是所希望的,主要由于绘图事件是在这个应用程序的窗口中进行绘制。
********************************************/QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEstruct stuLine//直线
{int startX;//按下点的xint startY;//按下点的yint endX;//终点的x(移动过程中的点,释放时的点)int endY;//终点的y(移动过程中的点,释放时的点)
};struct stuRectangle//矩形
{int startX;//按下点的xint startY;//按下点的yint width;//矩形宽int height;//矩形高
};struct stuEllipse//圆或者椭圆
{int startX;//按下点的xint startY;//按下点的yint width;//矩形宽int height;//矩形高
};struct stuTriangle//三角形(使用路径绘制)
{int startX;//按下点的xint startY;//按下点的yint endX;//终点的x(移动过程中的点,释放时的点)int endY;//终点的y(移动过程中的点,释放时的点)
};struct stuParallelogram//平行四边形(使用路径绘制)
{int startX;//按下点的xint startY;//按下点的yint endX;//终点的x(移动过程中的点,释放时的点)int endY;//终点的y(移动过程中的点,释放时的点)
};struct stuTrapezoid//梯形(路径绘制)
{int startX;//按下点的xint startY;//按下点的yint endX;//终点的x(移动过程中的点,释放时的点)int endY;//终点的y(移动过程中的点,释放时的点)
};struct stuDiamond//菱形(路径绘制)
{int startX;//按下点的xint startY;//按下点的yint endX;//终点的x(移动过程中的点,释放时的点)int endY;//终点的y(移动过程中的点,释放时的点)
};class Widget : public QWidget
{Q_OBJECTenum graphicType{//其实在这种情况下,只要给第一个赋值就行noShape = 0,line = 1,curve = 2,rectangle = 3,ellipse = 4,triangle = 5,//三角形Trapezoid = 6,//梯形Parallelogram = 7,//平行四边形diamond = 8//菱形};
public:Widget(QWidget *parent = nullptr);~Widget();
private:void initLineType();//初始化线型下拉列表void initPenBrushLine();//初始化画笔,画刷,以及线型等void setBrushPenColor();//设置画笔和画刷颜色(这里画笔和画刷相同颜色)bool isContainInRect(QPoint pos);//包含的点是否在矩形内void clearLastPaintLine();//清屏之后,给最后一个绘制的直线赋空void clearLastPaintRectangle();//清屏之后,给最后一个绘制的矩形赋空void clearLastPaintEllipse();//清屏之后,将最后一个绘制的椭圆赋空void clearLastPaintDiamond();//清屏之后,给最后一个绘制的菱形赋空void clearLastPaintParallelogram();//清屏之后,给最后一个绘制的平行四边形赋空void clearLastPaintTrapezoid();//清屏之后,给最后一个绘制的梯形赋空void clearLastPaintTriangle();//清屏之后,给最后一个绘制的三角形赋空
protected:void mousePressEvent(QMouseEvent *event);void mouseMoveEvent(QMouseEvent *event);void mouseReleaseEvent(QMouseEvent *event);void paintEvent(QPaintEvent *event);//绘制线
// void keyPressEvent(QKeyEvent *event);//按键事件(按键切换的时候与线宽设置相冲突,spinBox接收了事件)
private slots:void on_clearBtn_clicked();//清除画布上绘制的内容void on_colorBtn_clicked();//选择颜色void on_lineTypeCombox_activated(const QString &arg1);//选择的线型void on_checkBox_clicked(bool checked);//是否填充图形void on_spinBox_valueChanged(int arg1);//设置的线宽void on_lineBtn_clicked();//绘制直线void on_curveBtn_clicked();//绘制曲线void on_rectangleBtn_clicked();//绘制矩形void on_ellipseBtn_clicked();//绘制椭圆void on_triangleBtn_clicked();//绘制三角形void on_parallelogramBtn_clicked();//绘制平行四边形void on_TrapezoidBtn_clicked();//绘制梯形void on_diamondBtn_clicked();//绘制菱形void on_undoBtn_clicked();//撤销之前绘制的图形void on_screenshotSaveBtn_clicked();//截图保存private:Ui::Widget *ui;graphicType m_type;//当前绘制的图形所属图形的类型QPen m_pen;//画笔QBrush m_brush;//填充用的画刷QColor m_color;//绘制图形的颜色bool m_isFill;//是否填充图形true-是bool m_isClear;//是否清屏(为了清屏功能正常使用)bool m_isPress;//是否鼠标左键点击(为了解决点击线型下拉列表的时候,不让进入鼠标移动事件,从而引起绘图)QStack<graphicType> m_typeStack;//按序保存绘制图形的类型stuLine m_line;//暂存每段直线中的点QVector<stuLine> m_lineVec;//保存未清屏前所有直线的点QVector<QPen> m_penLineVec;//保存所有的直线的画笔stuRectangle m_rectangle;//暂存矩形中的点QVector<stuRectangle> m_rectangleVec;//保存未清屏前所有的矩形QVector<QPen> m_rectanglePen;//保存绘制每一个矩形的画笔QVector<QBrush> m_rectangleBrush;//保存之前绘制的图形的画刷stuEllipse m_ellipse;//暂存椭圆中的点QVector<stuEllipse> m_ellipseVec;//保存未清屏前所有绘制的椭圆QVector<QPen> m_ellipsePen;//保存绘制每一个椭圆的画笔QVector<QBrush> m_ellipseBrush;//保存每一个椭圆的填充色stuDiamond m_diamond;//暂存菱形中的点QVector<stuDiamond> m_diamondVec;//保存未清屏之前所有绘制菱形的点QVector<QPen> m_diamondPen;//保存绘制每一个菱形的画笔QVector<QBrush> m_diamondBrush;//保存每个菱形的画刷stuParallelogram m_parallelogram;//暂存平行四边形中的点QVector<stuParallelogram> m_parallelogramVec;//保存未清屏之前绘制平行四边形的点QVector<QPen> m_parallelogramPen;//保存每次绘制平行四边形的画笔QVector<QBrush> m_parallelogramBrush;//保存每个平行四边形的画刷stuTrapezoid m_trapezoid;//暂存梯形中的点QVector<stuTrapezoid> m_trapezoidVec;//暂存为清屏之前的点QVector<QPen> m_trapezoidPen;//保存每次绘制梯形的画笔QVector<QBrush> m_trapezoidBrush;//保存每个梯形的画刷stuTriangle m_triangle;//暂存三角形中的点QVector<stuTriangle> m_triangleVec;//保存未清屏之前绘制三角形QVector<QPen> m_trianglePen;//保存每次绘制三角形的画笔QVector<QBrush> m_triangleBrush;//保存每个三角形的画刷QVector<QPen> m_curvePen;//绘制曲线的画笔QVector<QVector<QPoint>> m_lines;//保存未清屏之前所有曲线的起始点和终止点
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QMouseEvent>
#include <QPainter>
#include <QColorDialog>
#include <QVector>
#include <QTextDocumentFragment>
#include <QScreen>
#include <QDesktopWidget>
#include <QDebug>const QString strSolidLine = QStringLiteral("实线");
const QString strDashLine = QStringLiteral("虚线");
const QString strDotLine = QStringLiteral("点画线");
const QString strDashDotLine = QStringLiteral("点线画线");
const QString strDashDotDotLine = QStringLiteral("线点点画线");
const QString strCustomDashLine = QStringLiteral("自定义虚线");Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);resize(1100,1000);initLineType();initPenBrushLine();
}Widget::~Widget()
{delete ui;
}void Widget::initLineType()
{QStringList lineTye;lineTye<<strSolidLine<<strDashLine<<strDotLine<<strDashDotLine<<strDashDotDotLine<<strCustomDashLine;ui->lineTypeCombox->insertItems(0,lineTye);
}void Widget::initPenBrushLine()
{m_color = QColor(Qt::darkRed);m_pen.setWidth(5);m_pen.setStyle(Qt::SolidLine);m_pen.setCapStyle(Qt::RoundCap);m_pen.setJoinStyle(Qt::RoundJoin);m_pen.setColor(m_color);m_brush.setColor(Qt::transparent);m_brush.setStyle(Qt::Dense2Pattern);m_isFill = false;m_type = Widget::curve;m_isPress = false;
}void Widget::setBrushPenColor()
{m_pen.setColor(m_color);if (m_isFill) {m_brush.setColor(m_color);}else {m_brush.setColor(Qt::transparent);}
}bool Widget::isContainInRect(QPoint pos)
{QRect rectRangle = QRect(6,70,rect().width()-12,rect().height()-70 - 12);if (rectRangle.contains(pos)) {return true;}return false;
}void Widget::clearLastPaintLine()
{m_line.startX = 0;m_line.startY = 0;m_line.endX = 0;m_line.endY = 0;
}void Widget::clearLastPaintRectangle()
{m_rectangle.startX = 0;m_rectangle.startY = 0;m_rectangle.width = 0;m_rectangle.height = 0;
}void Widget::clearLastPaintEllipse()
{m_ellipse.startX = 0;m_ellipse.startY = 0;m_ellipse.width = 0;m_ellipse.height = 0;
}void Widget::clearLastPaintDiamond()
{m_diamond.startX = 0;m_diamond.startY = 0;m_diamond.endX = 0;m_diamond.endY = 0;
}void Widget::clearLastPaintParallelogram()
{m_parallelogram.startX = 0;m_parallelogram.startY = 0;m_parallelogram.endX = 0;m_parallelogram.endY = 0;
}void Widget::clearLastPaintTrapezoid()
{m_trapezoid.startX = 0;m_trapezoid.startY = 0;m_trapezoid.endX = 0;m_trapezoid.endY = 0;
}void Widget::clearLastPaintTriangle()
{m_triangle.startX = 0;m_triangle.startY = 0;m_triangle.endX = 0;m_triangle.endY = 0;
}void Widget::mousePressEvent(QMouseEvent *event)
{bool isContain = isContainInRect(event->pos());if (event->button() == Qt::LeftButton && isContain) {m_isPress = true;QPoint startPos = event->pos();if (m_type == 1) {m_line.startX = startPos.x();m_line.startY = startPos.y();}else if (m_type == 2) {QVector<QPoint> lineVec;lineVec.append(startPos);m_lines.append(lineVec);m_curvePen.append(m_pen);update();}else if (m_type == 3) {m_rectangle.startX = startPos.x();m_rectangle.startY = startPos.y();}else if (m_type == 4) {m_ellipse.startX = startPos.x();m_ellipse.startY = startPos.y();}else if (m_type == 5) {m_triangle.startX = startPos.x();m_triangle.startY = startPos.y();}else if (m_type == 6) {m_trapezoid.startX = startPos.x();m_trapezoid.startY = startPos.y();}else if (m_type == 7) {m_parallelogram.startX = startPos.x();m_parallelogram.startY = startPos.y();}else if (m_type == 8) {m_diamond.startX = startPos.x();m_diamond.startY = startPos.y();}}QWidget::mousePressEvent(event);
}void Widget::mouseMoveEvent(QMouseEvent *event)
{bool isContain = isContainInRect(event->pos());if (event->buttons() == Qt::LeftButton && m_isPress && isContain) {QPoint curPos = event->pos();if (m_type == 1) {//直线m_line.endX = curPos.x();m_line.endY = curPos.y();update();}else if (m_type == 2) {//曲线if (!m_lines.size()) {QVector<QPoint> lineVec;m_lines.append(lineVec);}QVector<QPoint> &lineVec = m_lines.last();lineVec.append(curPos);update();}else if (m_type == 3) {//矩形m_rectangle.width = curPos.x() - m_rectangle.startX;m_rectangle.height = curPos.y() - m_rectangle.startY;update();}else if (m_type == 4) {//椭圆m_ellipse.width = curPos.x() - m_ellipse.startX;m_ellipse.height = curPos.y() - m_ellipse.startY;update();}else if (m_type == 5) {//三角形m_triangle.endX = curPos.x();m_triangle.endY = curPos.y();update();}else if (m_type == 6) {//梯形m_trapezoid.endX = curPos.x();m_trapezoid.endY = curPos.y();update();}else if (m_type == 7) {//平行四边形m_parallelogram.endX = curPos.x();m_parallelogram.endY = curPos.y();update();}else if (m_type == 8) {m_diamond.endX = curPos.x();m_diamond.endY = curPos.y();update();}}QWidget::mouseMoveEvent(event);
}void Widget::mouseReleaseEvent(QMouseEvent *event)
{bool isContain = isContainInRect(event->pos());if (event->button() == Qt::LeftButton && isContain) {QPoint endPos = event->pos();if (m_type == 1) {m_line.endX = endPos.x();m_line.endY = endPos.y();//此时只保存了每条直线的起点和终点m_lineVec.append(m_line);m_penLineVec.append(m_pen);//每条线对应的画笔储存m_typeStack.push(line);update();}else if (m_type == 2) {QVector<QPoint> &lineVec = m_lines.last();lineVec.append(endPos);m_typeStack.push(curve);update();}else if (m_type == 3) {m_rectangle.width = endPos.x() - m_rectangle.startX;m_rectangle.height = endPos.y() - m_rectangle.startY;m_rectangleVec.append(m_rectangle);m_rectanglePen.append(m_pen);m_rectangleBrush.append(m_brush);m_typeStack.push(rectangle);update();}else if (m_type == 4) {m_ellipse.width = endPos.x() - m_ellipse.startX;m_ellipse.height = endPos.y() - m_ellipse.startY;m_ellipseVec.append(m_ellipse);m_ellipsePen.append(m_pen);m_ellipseBrush.append(m_brush);m_typeStack.push(ellipse);update();}else if (m_type == 5) {m_triangle.endX = endPos.x();m_triangle.endY = endPos.y();m_triangleVec.append(m_triangle);m_trianglePen.append(m_pen);m_triangleBrush.append(m_brush);m_typeStack.push(triangle);update();}else if (m_type == 6) {m_trapezoid.endX = endPos.x();m_trapezoid.endY = endPos.y();m_trapezoidVec.append(m_trapezoid);m_trapezoidPen.append(m_pen);m_trapezoidBrush.append(m_brush);m_typeStack.push(Trapezoid);update();}else if (m_type == 7) {m_parallelogram.endX = endPos.x();m_parallelogram.endY = endPos.y();m_parallelogramVec.append(m_parallelogram);m_parallelogramPen.append(m_pen);m_parallelogramBrush.append(m_brush);m_typeStack.push(Parallelogram);update();}else if (m_type == 8) {m_diamond.endX = endPos.x();m_diamond.endY = endPos.y();m_diamondVec.append(m_diamond);m_diamondPen.append(m_pen);m_diamondBrush.append(m_brush);m_typeStack.push(diamond);update();}m_isPress = false;}QWidget::mouseReleaseEvent(event);
}void Widget::paintEvent(QPaintEvent *event)
{
#if 0QPainter painter(this);QPen pen;pen.setWidth(4);pen.setColor(Qt::red);pen.setCapStyle(Qt::RoundCap);pen.setJoinStyle(Qt::RoundJoin);pen.setStyle(Qt::SolidLine);painter.setPen(pen);painter.setRenderHint(QPainter::Antialiasing, true);for (int i = 0; i < m_lines.size(); ++i) {QVector<QPoint> &lines = m_lines[i];for (int j =0; j < lines.size() - 1; ++j) {painter.drawLine(lines[j],lines[j+1]);}}
#endifQPainter painter(this);painter.setPen(m_pen);painter.setBrush(m_brush);painter.setRenderHint(QPainter::Antialiasing, true);if (!m_isClear) {if (m_type == 1) {//绘制单个实时直线(画笔不能放在这里保存,因为鼠标开始移动的时候,都会进入这里,对于一个颜色的画笔就会追加很多遍,而实际只需要一次)painter.drawLine(QPoint(m_line.startX,m_line.startY),QPoint(m_line.endX,m_line.endY));}else if (m_type == 2) {//绘制所有的曲线for (int i = 0; i < m_lines.size(); ++i) {QVector<QPoint> &lines = m_lines[i];for (int j =0; j < lines.size() - 1; ++j) {painter.drawLine(lines[j],lines[j+1]);}}}else if (m_type == 3) {//绘制单个实时矩形painter.drawRect(m_rectangle.startX,m_rectangle.startY,m_rectangle.width,m_rectangle.height);}else if (m_type == 4) {//绘制单个实时椭圆painter.drawEllipse(m_ellipse.startX,m_ellipse.startY,m_ellipse.width,m_ellipse.height);}else if (m_type == 5) {//绘制单个实时三角形(通过路径绘制和直线绘制)//通过直线绘制三角形(目前没有填充,因为本质上是直线)#if 0painter.drawLine(m_triangle.startX,m_triangle.startY,m_triangle.endX,m_triangle.endY);if (m_triangle.endX > m_triangle.startX) {painter.drawLine(m_triangle.endX,m_triangle.endY,m_triangle.endX-2*(m_triangle.endX - m_triangle.startX),m_triangle.endY);painter.drawLine(m_triangle.endX-2*(m_triangle.endX - m_triangle.startX),m_triangle.endY,m_triangle.startX,m_triangle.startY);}else {//abs(m_triangle.endX - abs(m_triangle.endY -m_triangle.startY))painter.drawLine(m_triangle.endX,m_triangle.endY,m_triangle.endX + 2*(m_triangle.startX - m_triangle.endX),m_triangle.endY);painter.drawLine(m_triangle.endX + 2*(m_triangle.startX - m_triangle.endX),m_triangle.endY,m_triangle.startX,m_triangle.startY);}#endifif (m_triangle.endX > m_triangle.startX) {//通过路径绘制三角形是一个封闭的三角形可以填充QPainterPath path;path.moveTo(m_triangle.startX,m_triangle.startY);path.lineTo(m_triangle.startX,m_triangle.startY);path.lineTo(m_triangle.endX,m_triangle.endY);path.lineTo(m_triangle.endX - 2*(m_triangle.endX - m_triangle.startX),m_triangle.endY);path.lineTo(m_triangle.startX,m_triangle.startY);painter.drawPath(path);//可以绘制边框线
// painter.fillPath(path,m_brush);//使用该函数绘制的路径不能边框线}else {QPainterPath path;path.moveTo(m_triangle.startX,m_triangle.startY);path.lineTo(m_triangle.startX,m_triangle.startY);path.lineTo(m_triangle.endX,m_triangle.endY);path.lineTo(m_triangle.endX + 2*(m_triangle.startX - m_triangle.endX),m_triangle.endY);path.lineTo(m_triangle.startX,m_triangle.startY);painter.drawPath(path);
// painter.fillPath(path,m_brush);}}else if (m_type == 6) {if (m_trapezoid.startX < m_trapezoid.endX) {#if 1QPainterPath path;path.moveTo(m_trapezoid.startX,m_trapezoid.startY);path.lineTo(m_trapezoid.startX,m_trapezoid.startY);path.lineTo(m_trapezoid.startX-40,m_trapezoid.endY);path.lineTo(m_trapezoid.endX,m_trapezoid.endY);path.lineTo(m_trapezoid.endX-40,m_trapezoid.startY);path.lineTo(m_trapezoid.startX,m_trapezoid.startY);painter.drawPath(path);
// painter.fillPath(path,m_brush);#endif#if 0QPointF points[4] = {QPointF(m_trapezoid.startX,m_trapezoid.startY),QPointF(qAbs(m_trapezoid.startX-50),m_trapezoid.endY),QPointF(m_trapezoid.endX,m_trapezoid.endY),QPointF(qAbs(m_trapezoid.endX-50),m_trapezoid.startY)};painter.drawPolygon(points,4);//绘制多边形#endif}else {#if 1QPainterPath path;path.moveTo(m_trapezoid.startX,m_trapezoid.startY);path.lineTo(m_trapezoid.startX,m_trapezoid.startY);path.lineTo(m_trapezoid.endX+40,m_trapezoid.startY);path.lineTo(m_trapezoid.endX,m_trapezoid.endY);path.lineTo(m_trapezoid.startX+40,m_trapezoid.endY);path.lineTo(m_trapezoid.startX,m_trapezoid.startY);painter.drawPath(path);
// painter.fillPath(path,m_brush);#endif}}else if (m_type == 7) {QPainterPath path;path.moveTo(m_parallelogram.startX,m_parallelogram.startY);path.lineTo(m_parallelogram.startX,m_parallelogram.startY);path.lineTo(m_parallelogram.startX+30,m_parallelogram.endY);path.lineTo(m_parallelogram.endX,m_parallelogram.endY);path.lineTo(m_parallelogram.endX-30,m_parallelogram.startY);path.lineTo(m_parallelogram.startX,m_parallelogram.startY);painter.drawPath(path);
// painter.fillPath(path,m_brush);}else if (m_type == 8) {if (m_diamond.startY < m_diamond.endY && abs(m_diamond.startX - m_diamond.endX)<30) {QPainterPath path;path.moveTo(m_diamond.startX,m_diamond.startY);path.lineTo(m_diamond.startX,m_diamond.startY);path.lineTo(m_diamond.startX+40,m_diamond.startY+(m_diamond.endY-m_diamond.startY)/2);path.lineTo(m_diamond.startX,m_diamond.endY);path.lineTo(m_diamond.startX-40,m_diamond.startY+(m_diamond.endY-m_diamond.startY)/2);path.lineTo(m_diamond.startX,m_diamond.startY);painter.drawPath(path);
// painter.fillPath(path,m_brush);}else if (m_diamond.startX < m_diamond.endX && abs(m_diamond.endY-m_diamond.startY)<30) {QPainterPath path;path.moveTo(m_diamond.startX,m_diamond.startY);path.lineTo(m_diamond.startX,m_diamond.startY);path.lineTo(m_diamond.startX+abs(m_diamond.endX-m_diamond.startX)/2,m_diamond.startY-40);path.lineTo(m_diamond.endX,m_diamond.startY);path.lineTo(m_diamond.startX+abs(m_diamond.endX-m_diamond.startX)/2,m_diamond.startY+40);path.lineTo(m_diamond.startX,m_diamond.startY);painter.drawPath(path);
// painter.fillPath(path,m_brush);}else if (m_diamond.startY > m_diamond.endY && abs(m_diamond.startX - m_diamond.endX)<30) {QPainterPath path;path.moveTo(m_diamond.startX,m_diamond.startY);path.lineTo(m_diamond.startX,m_diamond.startY);path.lineTo(m_diamond.startX-40,m_diamond.startY-(m_diamond.startY-m_diamond.endY)/2);path.lineTo(m_diamond.startX,m_diamond.endY);path.lineTo(m_diamond.startX+40,m_diamond.startY-(m_diamond.startY-m_diamond.endY)/2);path.lineTo(m_diamond.startX,m_diamond.startY);painter.drawPath(path);
// painter.fillPath(path,m_brush);}else if (m_diamond.startX > m_diamond.endX && abs(m_diamond.endY-m_diamond.startY)<30) {QPainterPath path;path.moveTo(m_diamond.startX,m_diamond.startY);path.lineTo(m_diamond.startX,m_diamond.startY);path.lineTo(m_diamond.startX-(m_diamond.startX-m_diamond.endX)/2,m_diamond.startY+40);path.lineTo(m_diamond.endX,m_diamond.startY);path.lineTo(m_diamond.startX-(m_diamond.startX-m_diamond.endX)/2,m_diamond.startY-40);path.lineTo(m_diamond.startX,m_diamond.startY);painter.drawPath(path);
// painter.fillPath(path,m_brush);}}//在这之前只能只能绘制单个直线,下面将之前保存的直线绘制for (int i = 0; i < m_lineVec.size(); ++i) {//直线QPen pen = m_penLineVec[i];//重新创建变量并保存在pen中,之前使用m_pen导致功能出错painter.setPen(pen);painter.drawLine(m_lineVec[i].startX,m_lineVec[i].startY,m_lineVec[i].endX,m_lineVec[i].endY);}//将之前绘制的曲线在切换不同的图形绘制的时候再绘一遍for (int i = 0; i < m_lines.size(); ++i) {//曲线QPen pen = m_curvePen[i];painter.setPen(pen);QVector<QPoint> &lines = m_lines[i];for (int j =0; j < lines.size() - 1; ++j) {painter.drawLine(lines[j],lines[j+1]);}}//将之前绘制的矩形重新绘制上(感觉刷新页面的时候都需要重新绘制)for (int i = 0; i < m_rectangleVec.size(); ++i) {//矩形QPen pen = m_rectanglePen.at(i);QBrush brush = m_rectangleBrush[i];painter.setPen(pen);painter.setBrush(brush);painter.drawRect(m_rectangleVec[i].startX,m_rectangleVec[i].startY,m_rectangleVec[i].width,m_rectangleVec[i].height);}//将之前绘制的椭圆重新绘制(没有这段代码,就会出现洗一次绘制的时候将之前绘制的椭圆清除)for (int i = 0; i < m_ellipseVec.size(); ++i) {QPen pen = m_ellipsePen.at(i);QBrush brush = m_ellipseBrush.at(i);painter.setPen(pen);painter.setBrush(brush);painter.drawEllipse(m_ellipseVec[i].startX,m_ellipseVec[i].startY,m_ellipseVec[i].width,m_ellipseVec[i].height);}//将之前绘制的三角形重新绘制(没有这段代码,只能绘制单个三角形)for (int i = 0;i < m_triangleVec.size(); ++i) {QPen pen = m_trianglePen[i];QBrush brush = m_triangleBrush[i];painter.setPen(pen);painter.setBrush(brush);stuTriangle tempTriangle = m_triangleVec[i];if (tempTriangle.endX > tempTriangle.startX) {//通过路径绘制三角形是一个封闭的三角形可以填充QPainterPath path;path.moveTo(tempTriangle.startX,tempTriangle.startY);path.lineTo(tempTriangle.startX,tempTriangle.startY);path.lineTo(tempTriangle.endX,tempTriangle.endY);path.lineTo(tempTriangle.endX - 2*(tempTriangle.endX - tempTriangle.startX),tempTriangle.endY);path.lineTo(tempTriangle.startX,tempTriangle.startY);painter.drawPath(path);
// painter.fillPath(path,m_brush);}else {QPainterPath path;path.moveTo(tempTriangle.startX,tempTriangle.startY);path.lineTo(tempTriangle.startX,tempTriangle.startY);path.lineTo(tempTriangle.endX,tempTriangle.endY);path.lineTo(tempTriangle.endX + 2*(tempTriangle.startX - tempTriangle.endX),tempTriangle.endY);path.lineTo(tempTriangle.startX,tempTriangle.startY);painter.drawPath(path);
// painter.fillPath(path,m_brush);}}//将之前所有绘制的梯形重新绘制,(没有这段代码,就只绘制当前的梯形)for (int i = 0; i < m_trapezoidVec.size(); ++i) {QPen pen = m_trapezoidPen[i];QBrush brush = m_trapezoidBrush[i];painter.setPen(pen);painter.setBrush(brush);stuTrapezoid trapezoid = m_trapezoidVec[i];if (trapezoid.startX < trapezoid.endX) {QPainterPath path;path.moveTo(trapezoid.startX,trapezoid.startY);path.lineTo(trapezoid.startX,trapezoid.startY);path.lineTo(trapezoid.startX-40,trapezoid.endY);path.lineTo(trapezoid.endX,trapezoid.endY);path.lineTo(trapezoid.endX-40,trapezoid.startY);path.lineTo(trapezoid.startX,trapezoid.startY);painter.drawPath(path);
// painter.fillPath(path,m_brush);}else {QPainterPath path;path.moveTo(trapezoid.startX,trapezoid.startY);path.lineTo(trapezoid.startX,trapezoid.startY);path.lineTo(trapezoid.endX+40,trapezoid.startY);path.lineTo(trapezoid.endX,trapezoid.endY);path.lineTo(trapezoid.startX+40,trapezoid.endY);path.lineTo(trapezoid.startX,trapezoid.startY);painter.drawPath(path);
// painter.fillPath(path,m_brush);}}//绘制之前绘制的平行四边形for (int i = 0; i < m_parallelogramVec.size(); ++i) {QPen pen = m_parallelogramPen[i];QBrush brush = m_parallelogramBrush[i];painter.setPen(pen);painter.setBrush(brush);QPainterPath path;path.moveTo(m_parallelogramVec[i].startX,m_parallelogramVec[i].startY);path.lineTo(m_parallelogramVec[i].startX,m_parallelogramVec[i].startY);path.lineTo(m_parallelogramVec[i].startX+30,m_parallelogramVec[i].endY);path.lineTo(m_parallelogramVec[i].endX,m_parallelogramVec[i].endY);path.lineTo(m_parallelogramVec[i].endX-30,m_parallelogramVec[i].startY);path.lineTo(m_parallelogramVec[i].startX,m_parallelogramVec[i].startY);painter.drawPath(path);
// painter.fillPath(path,m_brush);}//绘制之前绘制的菱形(只有上下左右四个方向的绘制)for (int i = 0; i < m_diamondVec.size(); ++i) {stuDiamond tempDiamod = m_diamondVec[i];QBrush brush = m_diamondBrush[i];QPen pen = m_diamondPen[i];painter.setBrush(brush);painter.setPen(pen);if (tempDiamod.startY < tempDiamod.endY && abs(tempDiamod.startX - tempDiamod.endX)<30) {QPainterPath path;path.moveTo(tempDiamod.startX,tempDiamod.startY);path.lineTo(tempDiamod.startX,tempDiamod.startY);path.lineTo(tempDiamod.startX+40,tempDiamod.startY+(tempDiamod.endY-tempDiamod.startY)/2);path.lineTo(tempDiamod.startX,tempDiamod.endY);path.lineTo(tempDiamod.startX-40,tempDiamod.startY+(tempDiamod.endY-tempDiamod.startY)/2);path.lineTo(tempDiamod.startX,tempDiamod.startY);painter.drawPath(path);
// painter.fillPath(path,m_brush);}else if (tempDiamod.startX < tempDiamod.endX && abs(tempDiamod.endY-tempDiamod.startY)<30) {QPainterPath path;path.moveTo(tempDiamod.startX,tempDiamod.startY);path.lineTo(tempDiamod.startX,tempDiamod.startY);path.lineTo(tempDiamod.startX+abs(tempDiamod.endX-tempDiamod.startX)/2,tempDiamod.startY-40);path.lineTo(tempDiamod.endX,tempDiamod.startY);path.lineTo(tempDiamod.startX+abs(tempDiamod.endX-tempDiamod.startX)/2,tempDiamod.startY+40);path.lineTo(tempDiamod.startX,tempDiamod.startY);painter.drawPath(path);
// painter.fillPath(path,m_brush);}else if (tempDiamod.startY > tempDiamod.endY && abs(tempDiamod.startX - tempDiamod.endX)<30) {QPainterPath path;path.moveTo(tempDiamod.startX,tempDiamod.startY);path.lineTo(tempDiamod.startX,tempDiamod.startY);path.lineTo(tempDiamod.startX-40,tempDiamod.startY-(tempDiamod.startY-tempDiamod.endY)/2);path.lineTo(tempDiamod.startX,tempDiamod.endY);path.lineTo(tempDiamod.startX+40,tempDiamod.startY-(tempDiamod.startY-tempDiamod.endY)/2);path.lineTo(tempDiamod.startX,tempDiamod.startY);painter.drawPath(path);
// painter.fillPath(path,m_brush);}else if (tempDiamod.startX > tempDiamod.endX && abs(tempDiamod.endY-tempDiamod.startY)<30) {QPainterPath path;path.moveTo(tempDiamod.startX,tempDiamod.startY);path.lineTo(tempDiamod.startX,tempDiamod.startY);path.lineTo(tempDiamod.startX-(tempDiamod.startX-tempDiamod.endX)/2,tempDiamod.startY+40);path.lineTo(tempDiamod.endX,tempDiamod.startY);path.lineTo(tempDiamod.startX-(tempDiamod.startX-tempDiamod.endX)/2,tempDiamod.startY-40);path.lineTo(tempDiamod.startX,tempDiamod.startY);painter.drawPath(path);
// painter.fillPath(path,m_brush);}}}if (m_isClear) {//清除之前绘制的直线后,刷新界面时会绘制上一次最后绘制的直线,短暂停留clearLastPaintLine();clearLastPaintRectangle();clearLastPaintEllipse();clearLastPaintDiamond();clearLastPaintParallelogram();clearLastPaintTrapezoid();clearLastPaintTriangle();m_isClear = false;}QWidget::paintEvent(event);
}#if 0
void Widget::keyPressEvent(QKeyEvent *event)
{int type = event->key();switch (type) {case Qt::Key_1:m_type = Widget::line;break;case Qt::Key_2:m_type = Widget::curve;break;case Qt::Key_3:m_type = Widget::rectangle;break;case Qt::Key_4:m_type = Widget::ellipse;break;case Qt::Key_5:m_type = Widget::triangle;break;case Qt::Key_6:m_type = Widget::Trapezoid;break;case Qt::Key_7:m_type = Widget::Parallelogram;break;case Qt::Key_8:m_type = Widget::diamond;break;default:break;}QWidget::keyPressEvent(event);
}
#endifvoid Widget::on_clearBtn_clicked()
{m_isClear = true;QVector<stuLine>().swap(m_lineVec);//清除之前绘制的所有直线(否则清除后依旧会存在之前绘制的图形)QVector<QVector<QPoint>>().swap(m_lines);//清除之前绘制的所有曲线QVector<stuRectangle>().swap(m_rectangleVec);//清除之前绘制的矩形QVector<stuEllipse>().swap(m_ellipseVec);//清除之前绘制的椭圆QVector<stuTriangle>().swap(m_triangleVec);//清除之前绘制三角形QVector<stuTrapezoid>().swap(m_trapezoidVec);//清除之前绘制的梯形QVector<stuParallelogram>().swap(m_parallelogramVec);//清除之前绘制的平行四边形QVector<stuDiamond>().swap(m_diamondVec);//清除之前绘制的菱形QVector<QPen>().swap(m_penLineVec);//清空之前绘制直线的画笔QVector<QPen>().swap(m_rectanglePen);//清空之前绘制矩形的画笔QVector<QPen>().swap(m_ellipsePen);//清空之前绘制椭圆的画笔QVector<QPen>().swap(m_trianglePen);//清空之前绘制的三角形的画笔QVector<QPen>().swap(m_diamondPen);//清空之前绘制菱形的画笔QVector<QPen>().swap(m_parallelogramPen);//清空之前绘制平行四边形的画笔QVector<QPen>().swap(m_trapezoidPen);//清空之前绘制梯形的画笔QVector<QPen>().swap(m_curvePen);//清空之前绘制曲线的画笔QVector<QBrush>().swap(m_rectangleBrush);//清空之前绘制矩形的画刷QVector<QBrush>().swap(m_ellipseBrush);//清空之前绘制椭圆的画刷QVector<QBrush>().swap(m_diamondBrush);//清空之前绘制菱形的画刷QVector<QBrush>().swap(m_parallelogramBrush);//清空之前绘制的平行四边形的画刷QVector<QBrush>().swap(m_triangleBrush);//清空之前绘制的三角形的画刷QVector<QBrush>().swap(m_trapezoidBrush);//清空之前绘制的梯形的画刷QStack<graphicType>().swap(m_typeStack);//清空之前绘制的图形类型update();
}void Widget::on_colorBtn_clicked()
{QColor defaultColor = QRgb("#008B8B");QColorDialog colorDlg(this);colorDlg.setGeometry(200,200,300,280);//此句注释掉之后会再程序运行的时候提示信息colorDlg.setWindowTitle(QStringLiteral("颜色选择对话框"));colorDlg.setCurrentColor(defaultColor);if (colorDlg.exec() == QColorDialog::Accepted) {m_color = colorDlg.selectedColor();}//设置画笔画刷颜色setBrushPenColor();
//这种方式创建的颜色对话框不能避免程序运行时,会在应用程序输出栏中输出信息
// m_color = QColorDialog::getColor(defaultColor,this,QString(QStringLiteral("颜色选择对话框")),QColorDialog::ShowAlphaChannel);
}void Widget::on_lineTypeCombox_activated(const QString &arg1)
{if (arg1.compare(strSolidLine) == 0) {m_pen.setStyle(Qt::SolidLine);}else if (arg1.compare(strDashLine) == 0) {m_pen.setStyle(Qt::DashLine);}else if (arg1.compare(strDotLine) == 0) {m_pen.setStyle(Qt::DotLine);}else if (arg1.compare(strDashDotLine) == 0) {m_pen.setStyle(Qt::DashDotLine);}else if (arg1.compare(strDashDotDotLine) == 0) {m_pen.setStyle(Qt::DashDotDotLine);}else if (arg1.compare(strCustomDashLine) == 0) {m_pen.setStyle(Qt::CustomDashLine);}
}void Widget::on_checkBox_clicked(bool checked)
{(checked == true) ? m_isFill = true : m_isFill = false;setBrushPenColor();
}void Widget::on_spinBox_valueChanged(int arg1)
{m_pen.setWidth(arg1);
}void Widget::on_lineBtn_clicked()
{m_type = Widget::line;
}void Widget::on_curveBtn_clicked()
{m_type = Widget::curve;
}void Widget::on_rectangleBtn_clicked()
{m_type = Widget::rectangle;
}void Widget::on_ellipseBtn_clicked()
{m_type = Widget::ellipse;
}void Widget::on_triangleBtn_clicked()
{m_type = Widget::triangle;
}void Widget::on_parallelogramBtn_clicked()
{m_type = Widget::Parallelogram;
}void Widget::on_TrapezoidBtn_clicked()
{m_type = Widget::Trapezoid;
}void Widget::on_diamondBtn_clicked()
{m_type = Widget::diamond;
}void Widget::on_undoBtn_clicked()
{m_type = Widget::noShape;//之前没有加noShape,每次撤销都会剩下最后一个绘制的图形,//后来发现撤销时update()的时候最后一次的m_type没有被清空,会重新绘制一下最后的图形,//在不能完全撤销的情况下,在重新绘制,之前没有撤销的图像就会自动消失if (!m_typeStack.isEmpty()) {graphicType &type = m_typeStack.top();switch (type) {case line:if (m_lineVec.size() != 0) {m_lineVec.pop_back();m_penLineVec.pop_back();m_typeStack.pop_back();update();}break;case curve:if (m_lines.size() != 0) {m_lines.pop_back();m_curvePen.pop_back();m_typeStack.pop_back();update();}break;case rectangle:if (m_rectangleVec.size() != 0) {m_rectangleVec.pop_back();m_rectanglePen.pop_back();m_rectangleBrush.pop_back();m_typeStack.pop_back();update();}break;case ellipse:if (m_ellipseVec.size() != 0) {m_ellipseVec.pop_back();m_ellipsePen.pop_back();m_ellipseBrush.pop_back();m_typeStack.pop_back();update();}break;case diamond:if (m_diamondVec.size() != 0) {m_diamondVec.pop_back();m_diamondPen.pop_back();m_diamondBrush.pop_back();m_typeStack.pop_back();update();}break;case Parallelogram:if (m_parallelogramVec.size() != 0) {m_parallelogramVec.pop_back();m_parallelogramPen.pop_back();m_parallelogramBrush.pop_back();m_typeStack.pop_back();update();}break;case Trapezoid:if (m_trapezoidVec.size() != 0) {m_trapezoidVec.pop_back();m_trapezoidBrush.pop_back();m_trapezoidPen.pop_back();m_typeStack.pop_back();update();}break;case triangle:if (m_triangleVec.size() != 0) {m_triangleVec.pop_back();m_triangleBrush.pop_back();m_trianglePen.pop_back();m_typeStack.pop_back();update();}break;default:break;}}else {qDebug()<<QStringLiteral("之前绘制的图形已经撤销完!");}
}void Widget::on_screenshotSaveBtn_clicked()
{Screenshot::getInstance()->showFullScreen();//调用全屏显示的时候会调用showevent事件
}
screenshot.h
#ifndef SCREENSHOT_H
#define SCREENSHOT_H#include <QWidget>
#include <QPixmap>/********************************************======功能描述:=======1.点击截图按钮出现截图蒙层,2.按住鼠标选择矩形区域截图,3.拖动选中的矩形截图区域,4.保存矩形区域的截图,5.按下f键保存全屏截图,6.另存为和取消截图。
********************************************/class Screenshot:public QWidget
{
Q_OBJECTScreenshot();
public:static Screenshot * getInstance();//获取类对象private:void correctStartEndCoordinate(QPoint &startPos,QPoint &endPos);//纠正左上和右下坐标void displayScreenshotText(QPainter &painter,QString text);//分情况显示截图的文本信息void createSaveBtn();//创建选中区域后保存取消按钮void setBtnWidgetPos();//分情况设置按钮对话框的位置void setMaxSize(int width,int height);//设置最大的宽度,最大的高度void saveCaptrueFullScreen();//保存截取全屏void moveUpdateTopleftBottomRight(QPoint offset);//移动的时候更新左上坐标和右下坐标
protected:void mousePressEvent(QMouseEvent *event);//鼠标按下void mouseMoveEvent(QMouseEvent *event);//鼠标移动void mouseReleaseEvent(QMouseEvent *event);//鼠标释放void showEvent(QShowEvent *event);//创建蒙层,调用全屏显示的时候,该函数被触发void paintEvent(QPaintEvent *event);//绘制void keyPressEvent(QKeyEvent *event);//键盘事件,当按下f截全屏
private slots:void onSaveBtn();//保存截图void onCancelBtn();//取消截图void onSaveAsBtn();//截图另存为
private:QPixmap *m_widgetBack;//截图的蒙层背景QPixmap *m_fullMap;//抓取的全屏图片bool m_isScreenshot;//是否是截屏QPoint m_startPos;//开始点QPoint m_endPos;//结束点QPoint m_topleft;//左上角坐标QPoint m_bottomRight;//右上坐标QWidget *m_btnWidget;//保存按钮的窗口int m_maxWidth;//截图最大的宽度int m_maxHeight;//截图最大的高度QPoint m_startMove;//开始拖动的点static QScopedPointer<Screenshot> self;//暂存类对象
};#endif // SCREENSHOT_H
screenshot.cpp
#include "screenshot.h"
#include <QPainter>
#include <QMutex>
#include <QMutexLocker>
#include <QGuiApplication>
#include <QApplication>
#include <QDesktopWidget>
#include <QScreen>
#include <QMouseEvent>
#include <QPushButton>
#include <QHBoxLayout>
#include <QDateTime>
#include <QFileDialog>
#include <QDebug>QScopedPointer<Screenshot> Screenshot::self;
Screenshot::Screenshot()
:QWidget()
{}Screenshot *Screenshot::getInstance()
{if (self.isNull()) {static QMutex mutex;QMutexLocker locker(&mutex);if (self.isNull()) {self.reset(new Screenshot);}}return self.take();
}void Screenshot::correctStartEndCoordinate(QPoint &startPos, QPoint &endPos)
{if (startPos.x() < endPos.x() && startPos.y() < endPos.y()) {m_topleft = startPos;m_bottomRight = endPos;}else if (startPos.x() < endPos.x() && startPos.y() > endPos.y()) {m_topleft.setX(startPos.x());m_topleft.setY(endPos.y());m_bottomRight.setX(endPos.x());m_bottomRight.setY(startPos.y());}else if (startPos.x() > endPos.x() && startPos.y() > endPos.y()) {m_topleft = endPos;m_bottomRight = startPos;}else if (startPos.x() > endPos.x() && startPos.y() < endPos.y()) {m_topleft.setX(endPos.x());m_topleft.setY(startPos.y());m_bottomRight.setX(startPos.x());m_bottomRight.setY(endPos.y());}
}void Screenshot::displayScreenshotText(QPainter &painter,QString text)
{if ((m_topleft.y() > 0 && m_topleft.y() < 9) || m_topleft.y() ==0) {painter.drawText(m_topleft.x() + 2,m_topleft.y() + 16,text);}else {painter.drawText(m_topleft.x() + 2,m_topleft.y() - 10,text);}
}void Screenshot::createSaveBtn()
{m_btnWidget = new QWidget();m_btnWidget->setWindowFlag(Qt::FramelessWindowHint);//分情况设置按钮对话框的位置,当m_bottomRight.y()为最大高度,按钮对话框位于内部setBtnWidgetPos();QPushButton *saveBtn = new QPushButton(QStringLiteral("保存"),m_btnWidget);QPushButton *cancelBtn = new QPushButton(QStringLiteral("取消"),m_btnWidget);QPushButton *saveAsBtn = new QPushButton(QStringLiteral("另存为:"),m_btnWidget);saveBtn->setFixedSize(80,30);cancelBtn->setFixedSize(80,30);saveAsBtn->setFixedSize(80,30);QHBoxLayout *hLayout = new QHBoxLayout(m_btnWidget);hLayout->setSpacing(0);hLayout->setContentsMargins(0,0,0,0);hLayout->addWidget(cancelBtn);hLayout->addWidget(saveAsBtn);hLayout->addWidget(saveBtn);m_btnWidget->show();connect(saveBtn,&QPushButton::clicked,this,&Screenshot::onSaveBtn);connect(cancelBtn,&QPushButton::clicked,this,&Screenshot::onCancelBtn);connect(saveAsBtn,&QPushButton::clicked,this,&Screenshot::onSaveAsBtn);
}void Screenshot::setBtnWidgetPos()
{if (m_bottomRight.y() == m_maxHeight || (m_bottomRight.y() > m_maxHeight - 30 && m_bottomRight.y() < m_maxHeight)) {m_btnWidget->setGeometry(m_bottomRight.x() - 240,m_bottomRight.y() - 32,240,30);}else {m_btnWidget->setGeometry(m_bottomRight.x() - 240,m_bottomRight.y() + 2,240,30);}
}void Screenshot::setMaxSize(int width, int height)
{m_maxWidth = width;m_maxHeight = height;
}void Screenshot::saveCaptrueFullScreen()
{QString strFileName = QString("%1/picture-%2.png").arg(qApp->applicationDirPath()).arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss"));m_fullMap->save(strFileName,"png");//全屏保存close();
}void Screenshot::moveUpdateTopleftBottomRight(QPoint offset)
{m_topleft += offset;m_bottomRight += offset;if (m_topleft.x() < 0) {m_bottomRight.setX(m_bottomRight.x() - m_topleft.x());m_topleft.setX(0);}else if (m_topleft.y() < 0) {m_bottomRight.setY(m_bottomRight.y() - m_topleft.y());m_topleft.setY(0);}else if (m_bottomRight.x() > m_maxWidth) {m_topleft.setX(m_topleft.x() - (m_bottomRight.x() - m_maxWidth));m_bottomRight.setX(m_maxWidth);}else if (m_bottomRight.y() > m_maxHeight) {m_topleft.setY(m_topleft.y() - (m_bottomRight.y() - m_maxHeight));m_bottomRight.setY(m_maxHeight);}
}void Screenshot::mousePressEvent(QMouseEvent *event)
{if (m_isScreenshot && event->button() == Qt::LeftButton) {m_startPos = event->pos();}else if (!m_isScreenshot) {if (QRect(m_topleft,m_bottomRight).contains(event->pos())) {m_startMove = event->pos();setCursor(Qt::SizeAllCursor);m_btnWidget->hide();}else {m_startPos = event->pos();m_isScreenshot = true;}}QWidget::mousePressEvent(event);
}void Screenshot::mouseMoveEvent(QMouseEvent *event)
{if (event->buttons() == Qt::LeftButton && m_isScreenshot) {m_endPos = event->pos();correctStartEndCoordinate(m_startPos,m_endPos);}else if (!m_isScreenshot && event->buttons() == Qt::LeftButton) {QPoint offPos = event->pos() - m_startMove;moveUpdateTopleftBottomRight(offPos);m_startMove = event->pos();}update();
}void Screenshot::mouseReleaseEvent(QMouseEvent *event)
{if (m_isScreenshot) {m_isScreenshot = false;createSaveBtn();}else {setCursor(Qt::ArrowCursor);setBtnWidgetPos();m_btnWidget->show();}QWidget::mouseReleaseEvent(event);
}void Screenshot::showEvent(QShowEvent *event)
{m_isScreenshot = true;m_btnWidget = nullptr;//赋初值,避免野指针//相当于获取桌面的快照QScreen *screen = QGuiApplication::primaryScreen();m_fullMap = new QPixmap();*m_fullMap = screen->grabWindow(QApplication::desktop()->winId(),0,0,QApplication::desktop()->size().width(),QApplication::desktop()->size().height());//创建桌面大小的蒙层QPixmap *backMap = new QPixmap(QApplication::desktop()->size());backMap->fill(QColor(160,160,160,200));//在桌面大小的图片上绘制蒙层(作为中间的一层,这个必须有,否则直接在全屏的图片上绘制蒙层,截图后的图片也会含有蒙层)m_widgetBack = new QPixmap(*m_fullMap);QPainter paint(m_widgetBack);paint.drawPixmap(0,0,*backMap);setMaxSize(QApplication::desktop()->size().width(),QApplication::desktop()->size().height());
}void Screenshot::paintEvent(QPaintEvent *event)
{QPainter painter(this);QPen pen;pen.setWidth(4);pen.setColor(QColor(Qt::darkYellow));pen.setStyle(Qt::DashLine);painter.setPen(pen);painter.drawPixmap(0,0,*m_widgetBack);if (qAbs(m_topleft.x() - m_bottomRight.x()) != 0 && qAbs(m_topleft.y() - m_bottomRight.y()) != 0) {painter.drawPixmap(m_topleft,m_fullMap->copy(QRect(m_topleft,m_bottomRight)));painter.drawRect(QRect(m_topleft,m_bottomRight));//判断左上角的y坐标的位置,分情况显示文本QString strText = QStringLiteral("截图的大小:%1x%2 - %3x%4,(%5x%6)").arg(m_topleft.x()).arg(m_topleft.y()).arg(m_bottomRight.x()).arg(m_bottomRight.y()).arg(m_bottomRight.x()-m_topleft.x()).arg(m_bottomRight.y()-m_topleft.y());displayScreenshotText(painter,strText);}QWidget::paintEvent(event);
}void Screenshot::keyPressEvent(QKeyEvent *event)
{if (event->key() == Qt::Key_F) {saveCaptrueFullScreen();}else if (event->key() == Qt::Key_Escape) {onCancelBtn();}QWidget::keyPressEvent(event);
}void Screenshot::onSaveBtn()
{QString strFileName = QString("%1/pix-%2.png").arg(qApp->applicationDirPath()).arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss"));m_fullMap->copy(QRect(m_topleft,m_bottomRight)).save(strFileName,"png");//保存截图时选中的区域m_btnWidget->close();//虽然效果上可行,但是感觉怪怪的close();
}void Screenshot::onCancelBtn()
{close();if (m_btnWidget) {//此处若是指针m_btnWidget没有赋初值,就会存在野指针,从而导致程序崩溃m_btnWidget->close();}
}void Screenshot::onSaveAsBtn()
{QString strFileName = QFileDialog::getSaveFileName(this,QStringLiteral("另存为"),qApp->applicationDirPath(),"Images(*.png *.jpg)");m_fullMap->copy(QRect(m_topleft,m_bottomRight)).save(strFileName,"png");m_btnWidget->close();close();
}
以上便是所有的实现代码。