Qt实现截图保存功能
1.实现结果
截图样子如下图所示,显示坐标和大小,同时能够保存截图到本地文件,或者用于应用程序;可以拖拽调整大小,或者移动位置等功能;
2.实现方法
截图界面头文件
#ifndef SCREENWIDGET_H #define SCREENWIDGET_H #include <QWidget> #include <QMenu> #include <QPoint> #include <QSize> #include <QMouseEvent> #include "CutPicToolBar.h" enum LOCATION { LEFT, RIGHT, UP, DOWN, MIDLE, OUTRANGE, LEFTUP, LEFTDOWN, RIGHTUP, RIGHTDOWN }; //截屏对象类 class Screen { public: enum STATUS { SELECT, MOV, SET_W_H, RESIZE }; Screen() {} Screen(QSize size); void setStart(QPoint pos); void setEnd(QPoint pos); QPoint getStart(); QPoint getEnd(); QPoint getLeftUp(); QPoint getRightDown(); STATUS getStatus(); void setStatus(STATUS status); int width(); int height(); bool isInArea(QPoint pos); // 检测pos是否在截图区域内 void move(QPoint p); // 按 p 移动截图区域 LOCATION GetLocation(QPoint pos); private: QPoint leftUpPos, rightDownPos; //记录 截图区域 左上角、右下角 QPoint startPos, endPos; //记录 鼠标开始位置、结束位置 int maxWidth, maxHeight; //记录屏幕大小 STATUS status; //三个状态: 选择区域、移动区域、设置width height void cmpPoint(QPoint &s, QPoint &e);//比较两位置,判断左上角、右下角 }; //截屏窗口类 class ScreenWidget : public QWidget { Q_OBJECT public: static ScreenWidget *Instance(); explicit ScreenWidget(QWidget *parent = 0); CutPicToolBar m_CutPicToolBar; signals: void signalCutPic(QString type,QString para ); private: static QScopedPointer<ScreenWidget> self; QMenu *menu; //右键菜单对象 Screen *screen; //截屏对象 QPixmap *fullScreen; //保存全屏图像 QPixmap *bgScreen; //模糊背景图 QPoint movPos; //坐标 QString m_defaultPicDPath; bool m_bMousePressed = false; bool m_hasRect = false; LOCATION m_lo=OUTRANGE; protected: void contextMenuEvent(QContextMenuEvent *e); void mousePressEvent(QMouseEvent *e); void mouseMoveEvent(QMouseEvent *e); void mouseReleaseEvent(QMouseEvent *e); void paintEvent(QPaintEvent *e); void showEvent(QShowEvent *e); void keyPressEvent(QKeyEvent *event); private slots: void saveScreenOther(); }; #endif // SCREENWIDGET_H
截图界面cpp文件
#include "screenwidget.h" #include <QMutex> #include <QApplication> #include <QPainter> #include <QDesktopWidget> #include <QFileDialog> #include <QEvent> #include <QDateTime> #include <QStringList> #include <QRect> #pragma execution_character_set("utf-8") #if (QT_VERSION > QT_VERSION_CHECK(5,0,0)) #include <QScreen> #endif #define STRDATETIME qPrintable (QDateTime::currentDateTime().toString("yyyyMMddHHmmss")) Screen::Screen(QSize size) { maxWidth = size.width(); maxHeight = size.height(); startPos = QPoint(-1, -1); endPos = startPos; leftUpPos = startPos; rightDownPos = startPos; status = SELECT; } int Screen::width() { return maxWidth; } int Screen::height() { return maxHeight; } Screen::STATUS Screen::getStatus() { return status; } void Screen::setStatus(STATUS status) { this->status = status; } void Screen::setEnd(QPoint pos) { endPos = pos; leftUpPos = startPos; rightDownPos = endPos; cmpPoint(leftUpPos, rightDownPos); } void Screen::setStart(QPoint pos) { startPos = pos; } QPoint Screen::getEnd() { return endPos; } QPoint Screen::getStart() { return startPos; } QPoint Screen::getLeftUp() { return leftUpPos; } QPoint Screen::getRightDown() { return rightDownPos; } bool Screen::isInArea(QPoint pos) { if (pos.x() > leftUpPos.x() && pos.x() < rightDownPos.x() && pos.y() > leftUpPos.y() && pos.y() < rightDownPos.y()) { return true; } return false; } LOCATION Screen::GetLocation(QPoint pos) { LOCATION location= LOCATION::OUTRANGE; QRect Left, right, up, down, leftup, leftdown, rightup, rightdown, midle; int cornelw = 3; int width = rightDownPos.x() - leftUpPos.x(); int height= rightDownPos.y() - leftUpPos.y(); Left = QRect(leftUpPos.x() - cornelw, leftUpPos.y() + cornelw, 2 * cornelw, height-2 * cornelw); leftup = QRect(leftUpPos.x()-cornelw, leftUpPos.y()- cornelw,2* cornelw,2*cornelw); leftdown = QRect(leftUpPos.x() - cornelw, rightDownPos.y() - cornelw, 2 * cornelw, 2 * cornelw); right= QRect(rightDownPos.x() - cornelw, leftUpPos.y() + cornelw, 2 * cornelw, height-2 * cornelw); rightup= QRect(rightDownPos.x() - cornelw, leftUpPos.y() - cornelw, 2 * cornelw, 2 * cornelw); rightdown = QRect(rightDownPos.x() - cornelw, rightDownPos.y() - cornelw, 2 * cornelw, 2 * cornelw); up= QRect(leftUpPos.x() + cornelw, leftUpPos.y() - cornelw, width-2 * cornelw, 2 * cornelw); down= QRect(leftUpPos.x() + cornelw, rightDownPos.y() - cornelw, width- 2 * cornelw, 2 * cornelw); midle= QRect(leftUpPos.x() + cornelw, leftUpPos.y() + cornelw, width-2 * cornelw, height - 2 * cornelw); if (leftdown.contains(pos)) { location = LOCATION::LEFTDOWN; } if (Left.contains(pos)) { location = LOCATION::LEFT; } if (leftup.contains(pos)) { location = LOCATION::LEFTUP; } if (right.contains(pos)) { location = LOCATION::RIGHT; } if (rightup.contains(pos)) { location = LOCATION::RIGHTUP; } if (rightdown.contains(pos)) { location = LOCATION::RIGHTDOWN; } if (down.contains(pos)) { location = LOCATION::DOWN; } if (up.contains(pos)) { location = LOCATION::UP; } if (midle.contains(pos)) { location = LOCATION::MIDLE; } return location; } void Screen::move(QPoint p) { int lx = leftUpPos.x() + p.x(); int ly = leftUpPos.y() + p.y(); int rx = rightDownPos.x() + p.x(); int ry = rightDownPos.y() + p.y(); if (lx < 0) { lx = 0; rx -= p.x(); } if (ly < 0) { ly = 0; ry -= p.y(); } if (rx > maxWidth) { rx = maxWidth; lx -= p.x(); } if (ry > maxHeight) { ry = maxHeight; ly -= p.y(); } leftUpPos = QPoint(lx, ly); rightDownPos = QPoint(rx, ry); startPos = leftUpPos; endPos = rightDownPos; } void Screen::cmpPoint(QPoint &leftTop, QPoint &rightDown) { QPoint l = leftTop; QPoint r = rightDown; if (l.x() <= r.x()) { if (l.y() <= r.y()) { ; } else { leftTop.setY(r.y()); rightDown.setY(l.y()); } } else { if (l.y() < r.y()) { leftTop.setX(r.x()); rightDown.setX(l.x()); } else { QPoint tmp; tmp = leftTop; leftTop = rightDown; rightDown = tmp; } } } QScopedPointer<ScreenWidget> ScreenWidget::self; ScreenWidget *ScreenWidget::Instance() { if (self.isNull()) { static QMutex mutex; QMutexLocker locker(&mutex); if (self.isNull()) { self.reset(new ScreenWidget); } } return self.data(); } ScreenWidget::ScreenWidget(QWidget *parent) : QWidget(parent) { //menu = new QMenu(this); //QAction *serachface = new QAction(tr("截图搜索"), this); //QAction *quit = new QAction(tr("退出"), this); //connect(serachface, SIGNAL(triggered()), this, SLOT(saveScreen())); //connect(quit, SIGNAL(triggered()), this, SLOT(hide())); //直接触发窗口的close函数 ///* 添加菜单项 */ //menu->addAction(serachface); //menu->addAction(quit); // //取得屏幕大小 screen = new Screen(QApplication::desktop()->size()); //保存全屏图像 fullScreen = new QPixmap(); m_CutPicToolBar.setParent(this); m_CutPicToolBar.hide(); connect(m_CutPicToolBar.ui.pBSaveTo, &QPushButton::clicked, this, &ScreenWidget::saveScreenOther); connect(m_CutPicToolBar.ui.pBClose, &QPushButton::clicked, this, [=]() { hide(); m_CutPicToolBar.hide(); m_hasRect = false; }); connect(m_CutPicToolBar.ui.pBSearchFace, &QPushButton::clicked, this, [=]() { int x = screen->getLeftUp().x(); int y = screen->getLeftUp().y(); int w = screen->getRightDown().x() - x; int h = screen->getRightDown().y() - y; QString strPath = qApp->applicationDirPath(); strPath = strPath + "/CutPic/"; QDir dir(strPath); if (!dir.exists()) { dir.mkpath(strPath); } QString fileName = QString("%1screen_%2.png").arg(strPath).arg(STRDATETIME); fullScreen->copy(x, y, w, h).save(fileName, "png"); hide(); m_CutPicToolBar.hide(); m_hasRect = false; emit signalCutPic("SearchFace", fileName); }); setMouseTracking(true); } void ScreenWidget::paintEvent(QPaintEvent *) { int x = screen->getLeftUp().x(); int y = screen->getLeftUp().y(); int w = screen->getRightDown().x() - x; int h = screen->getRightDown().y() - y; QPainter painter(this); QPen pen; pen.setColor(QColor(116, 255, 126)); pen.setWidth(2); pen.setStyle(Qt::SolidLine); painter.setPen(pen); painter.drawPixmap(0, 0, *bgScreen); if (w != 0 && h != 0) { painter.drawPixmap(x, y, fullScreen->copy(x, y, w, h)); } painter.drawRect(x, y, w, h); //绘制四个边角 QBrush brush; //画刷。填充几何图形的调色板,由颜色和填充风格组成 int cwidth = 4; brush.setColor(QColor(116, 255, 126)); brush.setStyle(Qt::SolidPattern); painter.setBrush(brush); painter.drawRect(x, y, cwidth, cwidth); painter.drawRect(x + w - cwidth, y, cwidth, cwidth); painter.drawRect(x, y + h - cwidth, cwidth, cwidth); painter.drawRect(x + w - cwidth, y + h - cwidth, cwidth, cwidth); pen.setColor(Qt::yellow); painter.setPen(pen); painter.drawText(x + 2, y - 8, tr("截图坐标:(%1,%2)-图片大小:(%3,%4)").arg(x).arg(y).arg(w).arg(h)); //painter.drawText(x + 2, y - 8, tr("图片大小:( %1 x %2 )").arg(w).arg(h)); } void ScreenWidget::showEvent(QShowEvent *) { QPoint point(-1, -1); screen->setStart(point); screen->setEnd(point); #if (QT_VERSION <= QT_VERSION_CHECK(5,0,0)) *fullScreen = fullScreen->grabWindow(QApplication::desktop()->winId(), 0, 0, screen->width(), screen->height()); #else QScreen *pscreen = QApplication::primaryScreen(); *fullScreen = pscreen->grabWindow(QApplication::desktop()->winId(), 0, 0, screen->width(), screen->height()); #endif //设置透明度实现模糊背景 QPixmap pix(screen->width(), screen->height()); pix.fill((QColor(0, 0, 0, 125))); bgScreen = new QPixmap(*fullScreen); QPainter p(bgScreen); p.drawPixmap(0, 0, pix); m_CutPicToolBar.hide(); m_hasRect = false; } void ScreenWidget::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Escape) { hide(); m_CutPicToolBar.hide(); m_hasRect = false; } } void ScreenWidget::saveScreenOther() { QString name = QString("%1.png").arg(STRDATETIME); if (m_defaultPicDPath.length()!=0) { if (m_defaultPicDPath.right(1)!="/") { name ="/" + name; } name = m_defaultPicDPath + name; } QString fileName = QFileDialog::getSaveFileName(this, "保存图片", name, "png Files (*.png)"); if (fileName!="") { if (!fileName.endsWith(".png")) { fileName += ".png"; } QFileInfo info(fileName); m_defaultPicDPath = info.absolutePath(); if (fileName.length() > 0) { int x = screen->getLeftUp().x(); int y = screen->getLeftUp().y(); int w = screen->getRightDown().x() - x; int h = screen->getRightDown().y() - y; fullScreen->copy(x, y, w, h).save(fileName, "png"); } } hide(); m_CutPicToolBar.hide(); m_hasRect = false; } void ScreenWidget::mouseMoveEvent(QMouseEvent *e) { if (m_bMousePressed == true) { if (screen->getStatus() == Screen::SELECT) { screen->setEnd(e->pos()); m_hasRect = true; } else if (screen->getStatus() == Screen::MOV) { QPoint p(e->x() - movPos.x(), e->y() - movPos.y()); screen->move(p); movPos = e->pos(); } else if (screen->getStatus() == Screen::RESIZE) { QPoint point,pointright; switch (m_lo) { case LEFT: point = screen->getLeftUp(); point.setX(e->pos().x()); screen->setStart(point); screen->setEnd(screen->getRightDown()); break; case RIGHT: point = screen->getRightDown(); point.setX(e->pos().x()); screen->setEnd(point); break; case UP: point = screen->getLeftUp(); point.setY(e->pos().y()); screen->setStart(point); screen->setEnd(screen->getRightDown()); break; case DOWN: point = screen->getRightDown(); point.setY(e->pos().y()); screen->setEnd(point); break; case MIDLE: break; case OUTRANGE: break; case LEFTUP: point = e->pos(); screen->setStart(point); screen->setEnd(screen->getRightDown()); break; case LEFTDOWN: point = screen->getLeftUp(); pointright = screen->getRightDown(); point.setX(e->pos().x()); pointright.setY(e->pos().y()); screen->setStart(point); screen->setEnd(pointright); break; case RIGHTUP: point = screen->getLeftUp(); pointright = screen->getRightDown(); point.setY(e->pos().y()); pointright.setX(e->pos().x()); screen->setStart(point); screen->setEnd(pointright); break; case RIGHTDOWN: point = e->pos(); screen->setEnd(point); break; default: break; } } } LOCATION lo = screen->GetLocation(e->pos()); switch (lo) { case LEFT: setCursor(Qt::SizeHorCursor); break; case RIGHT: setCursor(Qt::SizeHorCursor); break; case UP: setCursor(Qt::SizeVerCursor); break; case DOWN: setCursor(Qt::SizeVerCursor); break; case MIDLE: setCursor(Qt::SizeAllCursor); break; case OUTRANGE: setCursor(Qt::ArrowCursor); break; case LEFTUP: setCursor(Qt::SizeFDiagCursor); break; case LEFTDOWN: setCursor(Qt::SizeBDiagCursor); break; case RIGHTUP: setCursor(Qt::SizeBDiagCursor); break; case RIGHTDOWN: setCursor(Qt::SizeFDiagCursor); break; default: setCursor(Qt::ArrowCursor); break; } this->repaint(); } void ScreenWidget::mousePressEvent(QMouseEvent *e) { m_bMousePressed = true; m_CutPicToolBar.hide(); if (m_hasRect) { LOCATION lo = screen->GetLocation(e->pos()); if (lo==LOCATION::OUTRANGE) { screen->setStart(e->pos()); screen->setStatus(Screen::SELECT); } else if (lo==LOCATION::MIDLE) { screen->setStatus(Screen::MOV); movPos = e->pos();//QPoint(screen->getLeftUp().x() - e->pos().x(), screen->getLeftUp().y() - e->pos().y()); } else { m_lo = lo; screen->setStatus(Screen::RESIZE); } } else { screen->setStatus(Screen::SELECT); m_hasRect = false; screen->setStart(e->pos()); } this->update(); } void ScreenWidget::mouseReleaseEvent(QMouseEvent *) { m_bMousePressed = false; if (screen->getStatus() == Screen::SELECT) { screen->setStatus(Screen::MOV); } else if (screen->getStatus() == Screen::MOV) { this->setCursor(Qt::ArrowCursor); } int x = screen->getRightDown().x()+2; int y = screen->getLeftUp().y(); m_CutPicToolBar.move(x, y); m_CutPicToolBar.show(); } void ScreenWidget::contextMenuEvent(QContextMenuEvent *) { /*this->setCursor(Qt::ArrowCursor); menu->exec(cursor().pos());*/ }
然后再需求截图的地方直接调用showFullScreen函数,就可以拖动鼠标进行截图了;
connect(ui.pBCutPic, &QPushButton::clicked, this, [=]() { ScreenWidget::Instance()->showFullScreen(); });
自己开发了一个股票智能分析软件,功能很强大,需要的关注微信公众号:QStockView