QT实现截屏功能
2015-05-28 11:59
253 查看
QT实现截屏功能 2011-05-18
17:27:57
分类: C/C++
最近因为需要开发一个类似QQ的截屏功能,花了不少的时间,开始的时候很多也不懂,不知道如何下手,在网上找了很多的资料,现已经实现了截屏,移动截屏选区,通过拖动选区的八个控制点来改变选区的大小。
QT实现截屏的原理是,当点击截屏按钮(菜单栏上的截屏按钮)时,调用fullScreenWidget对象getFullScreenPixmap()方法,返回当前屏幕的QPixmap图片对象。在构造调用窗体的构造函数中,关联信号与槽,使其在点击“截屏”按钮发送信息给fullScreenWidget对象对应的槽函数,以便加载当前的背景图片。
connect(newAct,SIGNAL(triggered()),this,SLOT(screenshot()));
connect(this,SIGNAL(setPixmap(QPixmap)),fullWidget,SLOT(loadBackgroundPixmap(QPixmap)));
在fullScreenWidget类中,主要是根据当前截屏的状态来实时的判断如果截取屏幕。我在类中定义了shotState枚举类型,用来判断当前截屏的状态。定义了QPoint beginPoint,endPoint,moveBeginPoint,moveEndPoint;四个对象主要用来记录开始,结束的截屏坐标。移动的开始,结束坐标。根据不同的截屏状态和这4个坐标点的值来计算截屏的区域。我的表达能力不太好,先把核心代码上面来。fullScreenWidget.h头文件代码如下:
#ifndef FULLSCREENWIDGET_H
#define FULLSCREENWIDGET_H
#include <QWidget>
#include <QPixmap>
#include <QPoint>
#include <QtGui>
#include <QPainter>
#include <QBrush>
class fullScreenWidget : public QWidget{
Q_OBJECT
public:
fullScreenWidget(); //构造函数
enum shotState{initShot,beginShot,finishShot,endShot,beginMoveShot,finishMoveShot,beginControl,finishControl}; //进行截屏的状态
//移动选区中的8个控制点,按照顺时针方向从左上控制点到左中控制点分配编号为1~8
enum controlPointEnum{moveControl0,moveControl1,moveControl2,moveControl3,moveControl4,moveControl5,moveControl6,moveControl7,moveControl8};
QPixmap getFullScreenPixmap(); //获取全屏的Pixmap
public slots:
void loadBackgroundPixmap(const QPixmap &bgPixmap);//加载背景Pixmap槽函数
void loadBackgroundPixmap(const QPixmap &bgPixmap, int x, int y, int width, int height); //加载背景pixmap槽函数,设置x,y,width,height
void cancelSelectedRect(); //取消选择区域
void savePixmap(); //保选取行为的方法
signals:
void finishPixmap(const QPixmap &finishPixmap); //完成切图后的图片,发送信号给连接者
private:
//选区框的8个点选取
QRect tlRect; //左上点
QRect trRect; //右上点
QRect blRect; //左下点
QRect brRect; //右下点
QRect tcRect; //上中点
QRect bcRect; //下中点
QRect lcRect;//左中点
QRect rcRect; //右中点
QPainter painter;
QPoint beginPoint,endPoint,moveBeginPoint,moveEndPoint;
QRect selectedRect; //选择区域
QPixmap loadPixmap,shotPixmap;
shotState currentShotState; //当前的截屏状态
controlPointEnum controlValue; //记录移动控制点的值
QAction *savePixmapAction; //保存图片行为
QAction *cancelAction; //取消选取行为
QAction *quitAction; //退出选取行为
QMenu *contextMenu; //选中区域右键菜单
int screenwidth; //整个屏幕的宽度
int screenheight; //整个屏幕的高度
int screenx; //选区的X
int screeny; //选区的Y
int tipWidth,tipHeight,infoWidth,infoHeight; //加载初始框的宽度,高度;显示坐标信息的宽度,高度
QRect getSelectedRect(); //获取选取
QRect getRect(const QPoint &beginPoint, const QPoint &endPoint); //根据两个点获取选取坐标
void initFullScreenWidget(); //初始化抓全屏的相关参数
bool isInSelectedRect(const QPoint &point); //判断该点是否在选中区域
void initSelectedMenu();//初始化右键菜单
void drawTipsText(); //在屏幕上打印提示信息
void drawSelectedPixmap(void); //在屏幕上画选取的屏幕
void updateBeginEndPointValue(const QRect &rect); //当移动选取后,对beginPoint,endPoint坐标进行重新修改
void checkMoveEndPoint(); //对移动的选区进行判断
void draw8ControlPoint(const QRect &rect);
void updateMouseShape(const QPoint &point); //更新鼠标的当前状态
void updateMoveControlMouseShape(controlPointEnum controlValue);
controlPointEnum getMoveControlState(const QPoint &point); //获取移动控制点状态
QRect getMoveAllSelectedRect(void); //获取移动整个选中的选区
QRect getMoveControlSelectedRect(void);//获取移动控制点的选区
int getMinValue(int num1, int num2);//获取两个数中的最小值
void drawXYWHInfo(void); //打印选取的x,y,h,w值信息
//重写基类方法
void keyPressEvent(QKeyEvent *event);
void paintEvent(QPaintEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseDoubleClickEvent(QMouseEvent *event);
void contextMenuEvent(QContextMenuEvent *event);
};
#endif
fullScreenWidget.cpp类的实现文件如下:
#include "fullScreenWidget.h"
fullScreenWidget::fullScreenWidget()
{
setWindowState(Qt::WindowActive|Qt::WindowFullScreen);
tipWidth = 300; //温馨提示框的宽度
tipHeight = 100; //温馨提示框的高度
infoWidth = 100; //坐标信息框的宽度
infoHeight = 50; //坐标信息框的高度
initFullScreenWidget();
}
void fullScreenWidget::initSelectedMenu()
{
savePixmapAction = new QAction(tr("保存选区"),this);
cancelAction = new QAction(tr("重选"),this);
quitAction = new QAction(tr("退出"),this);
contextMenu = new QMenu(this);
connect(savePixmapAction,SIGNAL(triggered()),this,SLOT(savePixmap()));
connect(cancelAction,SIGNAL(triggered()),this,SLOT(cancelSelectedRect()));
connect(quitAction,SIGNAL(triggered()),this,SLOT(hide()));
}
void fullScreenWidget::savePixmap()
{
QString fileName;
fileName = QFileDialog::getSaveFileName(this,tr("保存图片"),QDir::currentPath(),tr("Images
(*.jpg *.png *.bmp)"));
if(fileName.isNull())
return;
shotPixmap.save(fileName);
hide();
}
void fullScreenWidget::loadBackgroundPixmap(const QPixmap &bgPixmap)
{
int width,height;
width = QApplication::desktop()->size().width();
height = QApplication::desktop()->size().height();
loadBackgroundPixmap(bgPixmap,0,0,width,height);
}
void fullScreenWidget::loadBackgroundPixmap(const QPixmap &bgPixmap, int x, int y, int width, int height)
{
loadPixmap = bgPixmap;
screenx = x;
screeny = y;
screenwidth = width;
screenheight = height;
initFullScreenWidget();
}
QPixmap fullScreenWidget::getFullScreenPixmap()
{
initFullScreenWidget();
QPixmap result = QPixmap();
result = QPixmap::grabWindow(QApplication::desktop()->winId()); //抓取当前屏幕的图片
return result;
}
void fullScreenWidget::paintEvent(QPaintEvent *event)
{
QColor shadowColor;
shadowColor= QColor(0,0,0,100); //阴影颜色设置
painter.begin(this); //进行重绘
painter.setPen(QPen(Qt::blue,2,Qt::SolidLine,Qt::FlatCap));//设置画笔
painter.drawPixmap(screenx,screeny,loadPixmap); //将背景图片画到窗体上
painter.fillRect(screenx,screeny,screenwidth,screenheight,shadowColor); //画影罩效果
switch(currentShotState){
case initShot:
drawTipsText();
break;
case beginShot:
case finishShot:
selectedRect = getRect(beginPoint,endPoint); //获取选区
drawSelectedPixmap();
break;
case beginMoveShot:
case finishMoveShot:
selectedRect = getMoveAllSelectedRect(); //获取选区
drawSelectedPixmap();
break;
case beginControl:
case finishControl:
selectedRect = getMoveControlSelectedRect();
drawSelectedPixmap();
break;
default:
break;
}
drawXYWHInfo(); //打印坐标信息
painter.end(); //重绘结束
if(currentShotState == finishMoveShot || currentShotState == finishControl){
updateBeginEndPointValue(selectedRect); //当移动完选区后,更新beginPoint,endPoint;为下一次移动做准备工作
}
}
void fullScreenWidget::keyPressEvent(QKeyEvent *event)
{
if(event->key() == Qt::Key_Escape){
initFullScreenWidget();
hide();
}
}
void fullScreenWidget::mousePressEvent(QMouseEvent *event)
{
//当开始进行拖动进行选择区域时,确定开始选取的beginPoint坐标
if(event->button() == Qt::LeftButton && currentShotState == initShot){
currentShotState = beginShot; //设置当前状态为beginShot状态
beginPoint = event->pos();
}
//移动选区改变选区的所在位置
if(event->button() == Qt::LeftButton && isInSelectedRect(event->pos()) &&
getMoveControlState(event->pos()) == moveControl0){
currentShotState = beginMoveShot; //启用开始移动选取选项,beginMoveShot状态
moveBeginPoint = event->pos();
}
//移动控制点改变选区大小
if(event->button() == Qt::LeftButton && getMoveControlState(event->pos()) != moveControl0){
currentShotState = beginControl; //开始移动控制点
controlValue = getMoveControlState(event->pos());
moveBeginPoint = event->pos();
}
}
void fullScreenWidget::mouseReleaseEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton && currentShotState == beginShot){
currentShotState = finishShot;
endPoint = event->pos();
update();
}
if(event->button() == Qt::LeftButton && currentShotState == beginMoveShot){
currentShotState = finishMoveShot;
moveEndPoint = event->pos();
update();
}
//当前状态为beginControl状态时,设置状态为finishControl
if(event->button() == Qt::LeftButton && currentShotState == beginControl){
currentShotState = finishControl;
moveEndPoint = event->pos();
update();
}
}
void fullScreenWidget::mouseMoveEvent(QMouseEvent *event)
{
//当拖动时,动态的更新所选择的区域
if(currentShotState == beginShot){
endPoint = event->pos();
update();
}
//当确定选区后,对选区进行移动操作
if(currentShotState == beginMoveShot || currentShotState == beginControl){
moveEndPoint = event->pos();
update();
}
updateMouseShape(event->pos()); //修改鼠标的形状
setMouseTracking(true);
}
void fullScreenWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
if(currentShotState == finishShot || currentShotState == finishMoveShot || currentShotState == finishControl){
emit finishPixmap(shotPixmap); //当完成时发送finishPixmap信号
hide();
}
}
QRect fullScreenWidget::getRect(const QPoint &beginPoint, const QPoint &endPoint)
{
int x,y,width,height;
width = qAbs(beginPoint.x() - endPoint.x());
height = qAbs(beginPoint.y() - endPoint.y());
x = beginPoint.x() < endPoint.x() ? beginPoint.x() : endPoint.x();
y = beginPoint.y() < endPoint.y() ? beginPoint.y() : endPoint.y();
return QRect(x,y,width,height);
}
void fullScreenWidget::initFullScreenWidget()
{
currentShotState = initShot;
controlValue = moveControl0;
beginPoint =QPoint(0,0);
endPoint = QPoint(0,0);
moveBeginPoint = QPoint(0,0);
moveEndPoint = QPoint(0,0);
tlRect = QRect(0,0,0,0); //左上点
trRect = QRect(0,0,0,0); //上右点
blRect = QRect(0,0,0,0); //左下点
brRect = QRect(0,0,0,0); //右下点
tcRect = QRect(0,0,0,0); //上中点
bcRect = QRect(0,0,0,0); //下中点
lcRect = QRect(0,0,0,0); //左中点
rcRect = QRect(0,0,0,0); //右中点
setCursor(Qt::CrossCursor);
}
bool fullScreenWidget::isInSelectedRect(const QPoint &point)
{
int x,y;
QRect selectedRect;
if(currentShotState == initShot || currentShotState == beginShot)
return false;
selectedRect = getSelectedRect();
x = point.x();
y = point.y();
return selectedRect.contains(x,y);
}
void fullScreenWidget::cancelSelectedRect()
{
initFullScreenWidget();
update(); //进行重绘,将选取区域去掉
}
void fullScreenWidget::contextMenuEvent(QContextMenuEvent *event)
{
initSelectedMenu();
if(isInSelectedRect(event->pos())){
contextMenu->addAction(savePixmapAction);
}
else{
contextMenu->addAction(cancelAction);
contextMenu->addAction(quitAction);
}
contextMenu->exec(event->pos());
}
void fullScreenWidget::drawTipsText()
{
int x = (screenwidth - tipWidth)/2;
int y = (screenheight - tipHeight)/2;
QColor color = QColor(100,100,100,200);
QRect rect = QRect(x,y,tipWidth,tipHeight);
QString strTipsText = QString(tr("温馨提示\n鼠标拖动进行截屏;截屏区域内右键保存;\n截屏区域外右键取消;ESC退出;"));
painter.fillRect(rect,color);
painter.setPen(QPen(Qt::white));//设置画笔的颜色为白色
painter.drawText(rect,Qt::AlignCenter,strTipsText);
}
QRect fullScreenWidget::getSelectedRect()
{
if(currentShotState == beginMoveShot){
return getMoveAllSelectedRect();
}
else if(currentShotState == beginControl){
return getMoveControlSelectedRect();
}
else{
return getRect(beginPoint,endPoint);
}
}
void fullScreenWidget::updateBeginEndPointValue(const QRect &rect)
{
beginPoint = rect.topLeft();
endPoint = rect.bottomRight();
moveBeginPoint = QPoint(0,0);
moveEndPoint = QPoint(0,0);
}
void fullScreenWidget::checkMoveEndPoint()
{
int x,y;
QRect selectedRect = getRect(beginPoint, endPoint);
QPoint bottomRightPoint = selectedRect.bottomRight();
x = moveEndPoint.x() - moveBeginPoint.x();
y = moveEndPoint.y() - moveBeginPoint.y();
if(x + selectedRect.x() < 0){ //当移动后X坐标小于零时,则出现选区丢失,则计算出moveEndPoint的X最大坐标值,进行赋值
moveEndPoint.setX(qAbs(selectedRect.x()-moveBeginPoint.x()));
}
if(y + selectedRect.y() < 0){ //当移动后Y坐标小于零时,则出现选区丢失,则计算出moveEndPoint的Y最大坐标值,进行赋值
moveEndPoint.setY(qAbs(selectedRect.y() - moveBeginPoint.y()));
}
if(x + bottomRightPoint.x() > screenwidth){ //当移动选区后,出现超出整个屏幕的右面时,设置moveEndPoint的X的最大坐标
moveEndPoint.setX(screenwidth - bottomRightPoint.x() + moveBeginPoint.x());
}
if(y + bottomRightPoint.y() > screenheight){ //当移动选区后,出现超出整个屏幕的下面时,设置moveEndPoint的Y的最大坐标值
moveEndPoint.setY(screenheight - bottomRightPoint.y() + moveBeginPoint.y());
}
}
void fullScreenWidget::draw8ControlPoint(const QRect &rect)
{
int x,y;
QColor color= QColor(0,0,255); //画点的颜色设置
QPoint tlPoint = rect.topLeft(); //左上点
QPoint trPoint = rect.topRight(); //右上点
QPoint blPoint = rect.bottomLeft(); //左下点
QPoint brPoint = rect.bottomRight(); //右下点
x = (tlPoint.x()+trPoint.x())/2;
y = tlPoint.y();
QPoint tcPoint = QPoint(x,y);
x = (blPoint.x()+brPoint.x())/2;
y = blPoint.y();
QPoint bcPoint = QPoint(x,y);
x = tlPoint.x();
y = (tlPoint.y()+blPoint.y())/2;
QPoint lcPoint = QPoint(x,y);
x = trPoint.x();
y = (trPoint.y()+brPoint.y())/2;
QPoint rcPoint = QPoint(x,y);
tlRect = QRect(tlPoint.x()-2,tlPoint.y()-2,6,6); //左上点
trRect = QRect(trPoint.x()-2,trPoint.y()-2,6,6); //右上点
blRect = QRect(blPoint.x()-2,blPoint.y()-2,6,6); //左下点
brRect = QRect(brPoint.x()-2,brPoint.y()-2,6,6); //右下点
tcRect = QRect(tcPoint.x()-2,tcPoint.y()-2,6,6); //上中点
bcRect = QRect(bcPoint.x()-2,bcPoint.y()-2,6,6); //下中点
lcRect = QRect(lcPoint.x()-2,lcPoint.y()-2,6,6);//左中点
rcRect = QRect(rcPoint.x()-2,rcPoint.y()-2,6,6); //右中点
painter.fillRect(tlRect,color);
painter.fillRect(trRect,color);
painter.fillRect(blRect,color);
painter.fillRect(brRect,color);
painter.fillRect(tcRect,color);
painter.fillRect(bcRect,color);
painter.fillRect(lcRect,color);
painter.fillRect(rcRect,color);
}
void fullScreenWidget::updateMouseShape(const QPoint &point)
{
switch(currentShotState){
case initShot:
case beginShot:
setCursor(Qt::CrossCursor);
break;
case beginMoveShot:
setCursor(Qt::OpenHandCursor);
break;
case finishShot:
case finishMoveShot:
case finishControl:
if(getSelectedRect().contains(point))
setCursor(Qt::OpenHandCursor);
else
updateMoveControlMouseShape(getMoveControlState(point));
break;
case beginControl:
updateMoveControlMouseShape(controlValue); //调用函数对移动8个控制点进行鼠标状态的改变
break;
default:
setCursor(Qt::ArrowCursor);
break;
}
}
void fullScreenWidget::updateMoveControlMouseShape(controlPointEnum controlValue){
switch(controlValue){
case moveControl1:
case moveControl5:
setCursor(Qt::SizeFDiagCursor);
break;
case moveControl2:
case moveControl6:
setCursor(Qt::SizeVerCursor);
break;
case moveControl3:
case moveControl7:
setCursor(Qt::SizeBDiagCursor);
break;
case moveControl4:
case moveControl8:
setCursor(Qt::SizeHorCursor);
break;
default:
setCursor(Qt::ArrowCursor);
break;
}
}
fullScreenWidget::controlPointEnum fullScreenWidget::getMoveControlState(const QPoint &point)
{
fullScreenWidget::controlPointEnum result = moveControl0;
if(currentShotState == initShot || currentShotState == beginShot) {
result = moveControl0;
}
else if(tlRect.contains(point)){
result = moveControl1;
}
else if(tcRect.contains(point)){
result = moveControl2;
}
else if(trRect.contains(point)){
result = moveControl3;
}
else if(rcRect.contains(point)){
result = moveControl4;
}
else if(brRect.contains(point)){
result = moveControl5;
}
else if(bcRect.contains(point)){
result = moveControl6;
}
else if(blRect.contains(point)){
result = moveControl7;
}
else if(lcRect.contains(point)){
result = moveControl8;
}
else{
result = moveControl0;
}
return result;
}
QRect fullScreenWidget::getMoveAllSelectedRect(void)
{
QRect result;
QPoint tmpBeginPoint,tmpEndPoint;
int moveX,moveY;
checkMoveEndPoint(); //对移动选区进行判断,当移动的选区超出边界,则停止移动
moveX = moveEndPoint.x() - moveBeginPoint.x();
moveY = moveEndPoint.y() - moveBeginPoint.y();
tmpBeginPoint.setX(beginPoint.x() + moveX);
tmpBeginPoint.setY(beginPoint.y() + moveY);
tmpEndPoint.setX(endPoint.x() + moveX);
tmpEndPoint.setY(endPoint.y() + moveY);
result = getRect(tmpBeginPoint, tmpEndPoint);
return result;
}
QRect fullScreenWidget::getMoveControlSelectedRect(void)
{
int x,y,w,h;
QRect rect = getRect(beginPoint,endPoint);
QRect result;
switch(controlValue){
case moveControl1:
result = getRect(rect.bottomRight(),moveEndPoint);
return result;
break;
case moveControl2:
x = rect.x();
y = getMinValue(moveEndPoint.y(),rect.bottomLeft().y());
w = rect.width();
h = qAbs(moveEndPoint.y() - rect.bottomRight().y());
break;
case moveControl3:
result = getRect(rect.bottomLeft(),moveEndPoint);
return result;
break;
case moveControl4:
x = getMinValue(rect.x(),moveEndPoint.x());
y = rect.y();
w = qAbs(rect.bottomLeft().x() - moveEndPoint.x());
h = rect.height();
break;
case moveControl5:
result = getRect(rect.topLeft(),moveEndPoint);
return result;
break;
case moveControl6:
x = rect.x();
y = getMinValue(rect.y(),moveEndPoint.y());
w = rect.width();
h = qAbs(moveEndPoint.y() - rect.topLeft().y());
break;
case moveControl7:
result = getRect(moveEndPoint,rect.topRight());
return result;
break;
case moveControl8:
x = getMinValue(moveEndPoint.x(),rect.bottomRight().x());
y = rect.y();
w = qAbs(rect.bottomRight().x() - moveEndPoint.x());
h = rect.height();
break;
default:
result = getRect(beginPoint,endPoint);
return result;
break;
}
return QRect(x,y,w,h); //获取选区
}
int fullScreenWidget::getMinValue(int num1, int num2)
{
return num1<num2?num1:num2;
}
void fullScreenWidget::drawSelectedPixmap(void)
{
painter.drawRect(selectedRect); //画选中的矩形框
shotPixmap = loadPixmap.copy(selectedRect); //更新选区的Pixmap
if(selectedRect.width() > 0 && selectedRect.height()){
painter.drawPixmap(selectedRect.topLeft(),shotPixmap); //画选中区域的图片
}
draw8ControlPoint(selectedRect); //画出选区的8个控制点
}
void fullScreenWidget::drawXYWHInfo(void)
{
int x,y;
QColor color = QColor(239,234,228,200);
QRect rect;
QString strTipsText;
switch(currentShotState){
case beginShot:
case finishShot:
case beginMoveShot:
case finishMoveShot:
case beginControl:
case finishControl:
x = selectedRect.x() + 5;
y = selectedRect.y() > infoHeight ? selectedRect.y()-infoHeight:selectedRect.y();
rect = QRect(x,y,infoWidth,infoHeight);
strTipsText = QString(tr("
坐标信息\n x:%1 y:%2\n w:%3 h:%4")).arg(selectedRect.x(),4).arg(selectedRect.y(),4)
.arg(selectedRect.width(),4).arg(selectedRect.height(),4);
painter.fillRect(rect,color);
painter.setPen(QPen(Qt::black));//设置画笔的颜色为黑色
painter.drawText(rect,Qt::AlignLeft|Qt::AlignVCenter,strTipsText);
break;
default:
break;
}
}
screenshot.zip
您可以下载下来,进行测试使用。解压文件后,使用qtcreator工具进行加载screenshot.pro文件。执行qmake,build,run。即可。
注:因我提供的源代码在ubuntu操作系统上编写,如果您使用的是windows操作系统,可能需要qtcreator修改字符集为uft-8即可。本代码使用的是qt4.6.2进行编译,使用emacs编辑器进行编写。
17:27:57
分类: C/C++
最近因为需要开发一个类似QQ的截屏功能,花了不少的时间,开始的时候很多也不懂,不知道如何下手,在网上找了很多的资料,现已经实现了截屏,移动截屏选区,通过拖动选区的八个控制点来改变选区的大小。
QT实现截屏的原理是,当点击截屏按钮(菜单栏上的截屏按钮)时,调用fullScreenWidget对象getFullScreenPixmap()方法,返回当前屏幕的QPixmap图片对象。在构造调用窗体的构造函数中,关联信号与槽,使其在点击“截屏”按钮发送信息给fullScreenWidget对象对应的槽函数,以便加载当前的背景图片。
connect(newAct,SIGNAL(triggered()),this,SLOT(screenshot()));
connect(this,SIGNAL(setPixmap(QPixmap)),fullWidget,SLOT(loadBackgroundPixmap(QPixmap)));
在fullScreenWidget类中,主要是根据当前截屏的状态来实时的判断如果截取屏幕。我在类中定义了shotState枚举类型,用来判断当前截屏的状态。定义了QPoint beginPoint,endPoint,moveBeginPoint,moveEndPoint;四个对象主要用来记录开始,结束的截屏坐标。移动的开始,结束坐标。根据不同的截屏状态和这4个坐标点的值来计算截屏的区域。我的表达能力不太好,先把核心代码上面来。fullScreenWidget.h头文件代码如下:
#ifndef FULLSCREENWIDGET_H
#define FULLSCREENWIDGET_H
#include <QWidget>
#include <QPixmap>
#include <QPoint>
#include <QtGui>
#include <QPainter>
#include <QBrush>
class fullScreenWidget : public QWidget{
Q_OBJECT
public:
fullScreenWidget(); //构造函数
enum shotState{initShot,beginShot,finishShot,endShot,beginMoveShot,finishMoveShot,beginControl,finishControl}; //进行截屏的状态
//移动选区中的8个控制点,按照顺时针方向从左上控制点到左中控制点分配编号为1~8
enum controlPointEnum{moveControl0,moveControl1,moveControl2,moveControl3,moveControl4,moveControl5,moveControl6,moveControl7,moveControl8};
QPixmap getFullScreenPixmap(); //获取全屏的Pixmap
public slots:
void loadBackgroundPixmap(const QPixmap &bgPixmap);//加载背景Pixmap槽函数
void loadBackgroundPixmap(const QPixmap &bgPixmap, int x, int y, int width, int height); //加载背景pixmap槽函数,设置x,y,width,height
void cancelSelectedRect(); //取消选择区域
void savePixmap(); //保选取行为的方法
signals:
void finishPixmap(const QPixmap &finishPixmap); //完成切图后的图片,发送信号给连接者
private:
//选区框的8个点选取
QRect tlRect; //左上点
QRect trRect; //右上点
QRect blRect; //左下点
QRect brRect; //右下点
QRect tcRect; //上中点
QRect bcRect; //下中点
QRect lcRect;//左中点
QRect rcRect; //右中点
QPainter painter;
QPoint beginPoint,endPoint,moveBeginPoint,moveEndPoint;
QRect selectedRect; //选择区域
QPixmap loadPixmap,shotPixmap;
shotState currentShotState; //当前的截屏状态
controlPointEnum controlValue; //记录移动控制点的值
QAction *savePixmapAction; //保存图片行为
QAction *cancelAction; //取消选取行为
QAction *quitAction; //退出选取行为
QMenu *contextMenu; //选中区域右键菜单
int screenwidth; //整个屏幕的宽度
int screenheight; //整个屏幕的高度
int screenx; //选区的X
int screeny; //选区的Y
int tipWidth,tipHeight,infoWidth,infoHeight; //加载初始框的宽度,高度;显示坐标信息的宽度,高度
QRect getSelectedRect(); //获取选取
QRect getRect(const QPoint &beginPoint, const QPoint &endPoint); //根据两个点获取选取坐标
void initFullScreenWidget(); //初始化抓全屏的相关参数
bool isInSelectedRect(const QPoint &point); //判断该点是否在选中区域
void initSelectedMenu();//初始化右键菜单
void drawTipsText(); //在屏幕上打印提示信息
void drawSelectedPixmap(void); //在屏幕上画选取的屏幕
void updateBeginEndPointValue(const QRect &rect); //当移动选取后,对beginPoint,endPoint坐标进行重新修改
void checkMoveEndPoint(); //对移动的选区进行判断
void draw8ControlPoint(const QRect &rect);
void updateMouseShape(const QPoint &point); //更新鼠标的当前状态
void updateMoveControlMouseShape(controlPointEnum controlValue);
controlPointEnum getMoveControlState(const QPoint &point); //获取移动控制点状态
QRect getMoveAllSelectedRect(void); //获取移动整个选中的选区
QRect getMoveControlSelectedRect(void);//获取移动控制点的选区
int getMinValue(int num1, int num2);//获取两个数中的最小值
void drawXYWHInfo(void); //打印选取的x,y,h,w值信息
//重写基类方法
void keyPressEvent(QKeyEvent *event);
void paintEvent(QPaintEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseDoubleClickEvent(QMouseEvent *event);
void contextMenuEvent(QContextMenuEvent *event);
};
#endif
fullScreenWidget.cpp类的实现文件如下:
#include "fullScreenWidget.h"
fullScreenWidget::fullScreenWidget()
{
setWindowState(Qt::WindowActive|Qt::WindowFullScreen);
tipWidth = 300; //温馨提示框的宽度
tipHeight = 100; //温馨提示框的高度
infoWidth = 100; //坐标信息框的宽度
infoHeight = 50; //坐标信息框的高度
initFullScreenWidget();
}
void fullScreenWidget::initSelectedMenu()
{
savePixmapAction = new QAction(tr("保存选区"),this);
cancelAction = new QAction(tr("重选"),this);
quitAction = new QAction(tr("退出"),this);
contextMenu = new QMenu(this);
connect(savePixmapAction,SIGNAL(triggered()),this,SLOT(savePixmap()));
connect(cancelAction,SIGNAL(triggered()),this,SLOT(cancelSelectedRect()));
connect(quitAction,SIGNAL(triggered()),this,SLOT(hide()));
}
void fullScreenWidget::savePixmap()
{
QString fileName;
fileName = QFileDialog::getSaveFileName(this,tr("保存图片"),QDir::currentPath(),tr("Images
(*.jpg *.png *.bmp)"));
if(fileName.isNull())
return;
shotPixmap.save(fileName);
hide();
}
void fullScreenWidget::loadBackgroundPixmap(const QPixmap &bgPixmap)
{
int width,height;
width = QApplication::desktop()->size().width();
height = QApplication::desktop()->size().height();
loadBackgroundPixmap(bgPixmap,0,0,width,height);
}
void fullScreenWidget::loadBackgroundPixmap(const QPixmap &bgPixmap, int x, int y, int width, int height)
{
loadPixmap = bgPixmap;
screenx = x;
screeny = y;
screenwidth = width;
screenheight = height;
initFullScreenWidget();
}
QPixmap fullScreenWidget::getFullScreenPixmap()
{
initFullScreenWidget();
QPixmap result = QPixmap();
result = QPixmap::grabWindow(QApplication::desktop()->winId()); //抓取当前屏幕的图片
return result;
}
void fullScreenWidget::paintEvent(QPaintEvent *event)
{
QColor shadowColor;
shadowColor= QColor(0,0,0,100); //阴影颜色设置
painter.begin(this); //进行重绘
painter.setPen(QPen(Qt::blue,2,Qt::SolidLine,Qt::FlatCap));//设置画笔
painter.drawPixmap(screenx,screeny,loadPixmap); //将背景图片画到窗体上
painter.fillRect(screenx,screeny,screenwidth,screenheight,shadowColor); //画影罩效果
switch(currentShotState){
case initShot:
drawTipsText();
break;
case beginShot:
case finishShot:
selectedRect = getRect(beginPoint,endPoint); //获取选区
drawSelectedPixmap();
break;
case beginMoveShot:
case finishMoveShot:
selectedRect = getMoveAllSelectedRect(); //获取选区
drawSelectedPixmap();
break;
case beginControl:
case finishControl:
selectedRect = getMoveControlSelectedRect();
drawSelectedPixmap();
break;
default:
break;
}
drawXYWHInfo(); //打印坐标信息
painter.end(); //重绘结束
if(currentShotState == finishMoveShot || currentShotState == finishControl){
updateBeginEndPointValue(selectedRect); //当移动完选区后,更新beginPoint,endPoint;为下一次移动做准备工作
}
}
void fullScreenWidget::keyPressEvent(QKeyEvent *event)
{
if(event->key() == Qt::Key_Escape){
initFullScreenWidget();
hide();
}
}
void fullScreenWidget::mousePressEvent(QMouseEvent *event)
{
//当开始进行拖动进行选择区域时,确定开始选取的beginPoint坐标
if(event->button() == Qt::LeftButton && currentShotState == initShot){
currentShotState = beginShot; //设置当前状态为beginShot状态
beginPoint = event->pos();
}
//移动选区改变选区的所在位置
if(event->button() == Qt::LeftButton && isInSelectedRect(event->pos()) &&
getMoveControlState(event->pos()) == moveControl0){
currentShotState = beginMoveShot; //启用开始移动选取选项,beginMoveShot状态
moveBeginPoint = event->pos();
}
//移动控制点改变选区大小
if(event->button() == Qt::LeftButton && getMoveControlState(event->pos()) != moveControl0){
currentShotState = beginControl; //开始移动控制点
controlValue = getMoveControlState(event->pos());
moveBeginPoint = event->pos();
}
}
void fullScreenWidget::mouseReleaseEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton && currentShotState == beginShot){
currentShotState = finishShot;
endPoint = event->pos();
update();
}
if(event->button() == Qt::LeftButton && currentShotState == beginMoveShot){
currentShotState = finishMoveShot;
moveEndPoint = event->pos();
update();
}
//当前状态为beginControl状态时,设置状态为finishControl
if(event->button() == Qt::LeftButton && currentShotState == beginControl){
currentShotState = finishControl;
moveEndPoint = event->pos();
update();
}
}
void fullScreenWidget::mouseMoveEvent(QMouseEvent *event)
{
//当拖动时,动态的更新所选择的区域
if(currentShotState == beginShot){
endPoint = event->pos();
update();
}
//当确定选区后,对选区进行移动操作
if(currentShotState == beginMoveShot || currentShotState == beginControl){
moveEndPoint = event->pos();
update();
}
updateMouseShape(event->pos()); //修改鼠标的形状
setMouseTracking(true);
}
void fullScreenWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
if(currentShotState == finishShot || currentShotState == finishMoveShot || currentShotState == finishControl){
emit finishPixmap(shotPixmap); //当完成时发送finishPixmap信号
hide();
}
}
QRect fullScreenWidget::getRect(const QPoint &beginPoint, const QPoint &endPoint)
{
int x,y,width,height;
width = qAbs(beginPoint.x() - endPoint.x());
height = qAbs(beginPoint.y() - endPoint.y());
x = beginPoint.x() < endPoint.x() ? beginPoint.x() : endPoint.x();
y = beginPoint.y() < endPoint.y() ? beginPoint.y() : endPoint.y();
return QRect(x,y,width,height);
}
void fullScreenWidget::initFullScreenWidget()
{
currentShotState = initShot;
controlValue = moveControl0;
beginPoint =QPoint(0,0);
endPoint = QPoint(0,0);
moveBeginPoint = QPoint(0,0);
moveEndPoint = QPoint(0,0);
tlRect = QRect(0,0,0,0); //左上点
trRect = QRect(0,0,0,0); //上右点
blRect = QRect(0,0,0,0); //左下点
brRect = QRect(0,0,0,0); //右下点
tcRect = QRect(0,0,0,0); //上中点
bcRect = QRect(0,0,0,0); //下中点
lcRect = QRect(0,0,0,0); //左中点
rcRect = QRect(0,0,0,0); //右中点
setCursor(Qt::CrossCursor);
}
bool fullScreenWidget::isInSelectedRect(const QPoint &point)
{
int x,y;
QRect selectedRect;
if(currentShotState == initShot || currentShotState == beginShot)
return false;
selectedRect = getSelectedRect();
x = point.x();
y = point.y();
return selectedRect.contains(x,y);
}
void fullScreenWidget::cancelSelectedRect()
{
initFullScreenWidget();
update(); //进行重绘,将选取区域去掉
}
void fullScreenWidget::contextMenuEvent(QContextMenuEvent *event)
{
initSelectedMenu();
if(isInSelectedRect(event->pos())){
contextMenu->addAction(savePixmapAction);
}
else{
contextMenu->addAction(cancelAction);
contextMenu->addAction(quitAction);
}
contextMenu->exec(event->pos());
}
void fullScreenWidget::drawTipsText()
{
int x = (screenwidth - tipWidth)/2;
int y = (screenheight - tipHeight)/2;
QColor color = QColor(100,100,100,200);
QRect rect = QRect(x,y,tipWidth,tipHeight);
QString strTipsText = QString(tr("温馨提示\n鼠标拖动进行截屏;截屏区域内右键保存;\n截屏区域外右键取消;ESC退出;"));
painter.fillRect(rect,color);
painter.setPen(QPen(Qt::white));//设置画笔的颜色为白色
painter.drawText(rect,Qt::AlignCenter,strTipsText);
}
QRect fullScreenWidget::getSelectedRect()
{
if(currentShotState == beginMoveShot){
return getMoveAllSelectedRect();
}
else if(currentShotState == beginControl){
return getMoveControlSelectedRect();
}
else{
return getRect(beginPoint,endPoint);
}
}
void fullScreenWidget::updateBeginEndPointValue(const QRect &rect)
{
beginPoint = rect.topLeft();
endPoint = rect.bottomRight();
moveBeginPoint = QPoint(0,0);
moveEndPoint = QPoint(0,0);
}
void fullScreenWidget::checkMoveEndPoint()
{
int x,y;
QRect selectedRect = getRect(beginPoint, endPoint);
QPoint bottomRightPoint = selectedRect.bottomRight();
x = moveEndPoint.x() - moveBeginPoint.x();
y = moveEndPoint.y() - moveBeginPoint.y();
if(x + selectedRect.x() < 0){ //当移动后X坐标小于零时,则出现选区丢失,则计算出moveEndPoint的X最大坐标值,进行赋值
moveEndPoint.setX(qAbs(selectedRect.x()-moveBeginPoint.x()));
}
if(y + selectedRect.y() < 0){ //当移动后Y坐标小于零时,则出现选区丢失,则计算出moveEndPoint的Y最大坐标值,进行赋值
moveEndPoint.setY(qAbs(selectedRect.y() - moveBeginPoint.y()));
}
if(x + bottomRightPoint.x() > screenwidth){ //当移动选区后,出现超出整个屏幕的右面时,设置moveEndPoint的X的最大坐标
moveEndPoint.setX(screenwidth - bottomRightPoint.x() + moveBeginPoint.x());
}
if(y + bottomRightPoint.y() > screenheight){ //当移动选区后,出现超出整个屏幕的下面时,设置moveEndPoint的Y的最大坐标值
moveEndPoint.setY(screenheight - bottomRightPoint.y() + moveBeginPoint.y());
}
}
void fullScreenWidget::draw8ControlPoint(const QRect &rect)
{
int x,y;
QColor color= QColor(0,0,255); //画点的颜色设置
QPoint tlPoint = rect.topLeft(); //左上点
QPoint trPoint = rect.topRight(); //右上点
QPoint blPoint = rect.bottomLeft(); //左下点
QPoint brPoint = rect.bottomRight(); //右下点
x = (tlPoint.x()+trPoint.x())/2;
y = tlPoint.y();
QPoint tcPoint = QPoint(x,y);
x = (blPoint.x()+brPoint.x())/2;
y = blPoint.y();
QPoint bcPoint = QPoint(x,y);
x = tlPoint.x();
y = (tlPoint.y()+blPoint.y())/2;
QPoint lcPoint = QPoint(x,y);
x = trPoint.x();
y = (trPoint.y()+brPoint.y())/2;
QPoint rcPoint = QPoint(x,y);
tlRect = QRect(tlPoint.x()-2,tlPoint.y()-2,6,6); //左上点
trRect = QRect(trPoint.x()-2,trPoint.y()-2,6,6); //右上点
blRect = QRect(blPoint.x()-2,blPoint.y()-2,6,6); //左下点
brRect = QRect(brPoint.x()-2,brPoint.y()-2,6,6); //右下点
tcRect = QRect(tcPoint.x()-2,tcPoint.y()-2,6,6); //上中点
bcRect = QRect(bcPoint.x()-2,bcPoint.y()-2,6,6); //下中点
lcRect = QRect(lcPoint.x()-2,lcPoint.y()-2,6,6);//左中点
rcRect = QRect(rcPoint.x()-2,rcPoint.y()-2,6,6); //右中点
painter.fillRect(tlRect,color);
painter.fillRect(trRect,color);
painter.fillRect(blRect,color);
painter.fillRect(brRect,color);
painter.fillRect(tcRect,color);
painter.fillRect(bcRect,color);
painter.fillRect(lcRect,color);
painter.fillRect(rcRect,color);
}
void fullScreenWidget::updateMouseShape(const QPoint &point)
{
switch(currentShotState){
case initShot:
case beginShot:
setCursor(Qt::CrossCursor);
break;
case beginMoveShot:
setCursor(Qt::OpenHandCursor);
break;
case finishShot:
case finishMoveShot:
case finishControl:
if(getSelectedRect().contains(point))
setCursor(Qt::OpenHandCursor);
else
updateMoveControlMouseShape(getMoveControlState(point));
break;
case beginControl:
updateMoveControlMouseShape(controlValue); //调用函数对移动8个控制点进行鼠标状态的改变
break;
default:
setCursor(Qt::ArrowCursor);
break;
}
}
void fullScreenWidget::updateMoveControlMouseShape(controlPointEnum controlValue){
switch(controlValue){
case moveControl1:
case moveControl5:
setCursor(Qt::SizeFDiagCursor);
break;
case moveControl2:
case moveControl6:
setCursor(Qt::SizeVerCursor);
break;
case moveControl3:
case moveControl7:
setCursor(Qt::SizeBDiagCursor);
break;
case moveControl4:
case moveControl8:
setCursor(Qt::SizeHorCursor);
break;
default:
setCursor(Qt::ArrowCursor);
break;
}
}
fullScreenWidget::controlPointEnum fullScreenWidget::getMoveControlState(const QPoint &point)
{
fullScreenWidget::controlPointEnum result = moveControl0;
if(currentShotState == initShot || currentShotState == beginShot) {
result = moveControl0;
}
else if(tlRect.contains(point)){
result = moveControl1;
}
else if(tcRect.contains(point)){
result = moveControl2;
}
else if(trRect.contains(point)){
result = moveControl3;
}
else if(rcRect.contains(point)){
result = moveControl4;
}
else if(brRect.contains(point)){
result = moveControl5;
}
else if(bcRect.contains(point)){
result = moveControl6;
}
else if(blRect.contains(point)){
result = moveControl7;
}
else if(lcRect.contains(point)){
result = moveControl8;
}
else{
result = moveControl0;
}
return result;
}
QRect fullScreenWidget::getMoveAllSelectedRect(void)
{
QRect result;
QPoint tmpBeginPoint,tmpEndPoint;
int moveX,moveY;
checkMoveEndPoint(); //对移动选区进行判断,当移动的选区超出边界,则停止移动
moveX = moveEndPoint.x() - moveBeginPoint.x();
moveY = moveEndPoint.y() - moveBeginPoint.y();
tmpBeginPoint.setX(beginPoint.x() + moveX);
tmpBeginPoint.setY(beginPoint.y() + moveY);
tmpEndPoint.setX(endPoint.x() + moveX);
tmpEndPoint.setY(endPoint.y() + moveY);
result = getRect(tmpBeginPoint, tmpEndPoint);
return result;
}
QRect fullScreenWidget::getMoveControlSelectedRect(void)
{
int x,y,w,h;
QRect rect = getRect(beginPoint,endPoint);
QRect result;
switch(controlValue){
case moveControl1:
result = getRect(rect.bottomRight(),moveEndPoint);
return result;
break;
case moveControl2:
x = rect.x();
y = getMinValue(moveEndPoint.y(),rect.bottomLeft().y());
w = rect.width();
h = qAbs(moveEndPoint.y() - rect.bottomRight().y());
break;
case moveControl3:
result = getRect(rect.bottomLeft(),moveEndPoint);
return result;
break;
case moveControl4:
x = getMinValue(rect.x(),moveEndPoint.x());
y = rect.y();
w = qAbs(rect.bottomLeft().x() - moveEndPoint.x());
h = rect.height();
break;
case moveControl5:
result = getRect(rect.topLeft(),moveEndPoint);
return result;
break;
case moveControl6:
x = rect.x();
y = getMinValue(rect.y(),moveEndPoint.y());
w = rect.width();
h = qAbs(moveEndPoint.y() - rect.topLeft().y());
break;
case moveControl7:
result = getRect(moveEndPoint,rect.topRight());
return result;
break;
case moveControl8:
x = getMinValue(moveEndPoint.x(),rect.bottomRight().x());
y = rect.y();
w = qAbs(rect.bottomRight().x() - moveEndPoint.x());
h = rect.height();
break;
default:
result = getRect(beginPoint,endPoint);
return result;
break;
}
return QRect(x,y,w,h); //获取选区
}
int fullScreenWidget::getMinValue(int num1, int num2)
{
return num1<num2?num1:num2;
}
void fullScreenWidget::drawSelectedPixmap(void)
{
painter.drawRect(selectedRect); //画选中的矩形框
shotPixmap = loadPixmap.copy(selectedRect); //更新选区的Pixmap
if(selectedRect.width() > 0 && selectedRect.height()){
painter.drawPixmap(selectedRect.topLeft(),shotPixmap); //画选中区域的图片
}
draw8ControlPoint(selectedRect); //画出选区的8个控制点
}
void fullScreenWidget::drawXYWHInfo(void)
{
int x,y;
QColor color = QColor(239,234,228,200);
QRect rect;
QString strTipsText;
switch(currentShotState){
case beginShot:
case finishShot:
case beginMoveShot:
case finishMoveShot:
case beginControl:
case finishControl:
x = selectedRect.x() + 5;
y = selectedRect.y() > infoHeight ? selectedRect.y()-infoHeight:selectedRect.y();
rect = QRect(x,y,infoWidth,infoHeight);
strTipsText = QString(tr("
坐标信息\n x:%1 y:%2\n w:%3 h:%4")).arg(selectedRect.x(),4).arg(selectedRect.y(),4)
.arg(selectedRect.width(),4).arg(selectedRect.height(),4);
painter.fillRect(rect,color);
painter.setPen(QPen(Qt::black));//设置画笔的颜色为黑色
painter.drawText(rect,Qt::AlignLeft|Qt::AlignVCenter,strTipsText);
break;
default:
break;
}
}
screenshot.zip
您可以下载下来,进行测试使用。解压文件后,使用qtcreator工具进行加载screenshot.pro文件。执行qmake,build,run。即可。
注:因我提供的源代码在ubuntu操作系统上编写,如果您使用的是windows操作系统,可能需要qtcreator修改字符集为uft-8即可。本代码使用的是qt4.6.2进行编译,使用emacs编辑器进行编写。
相关文章推荐
- Qt——QT实现截屏功能
- Qt实用技巧:截屏功能的实现
- QT实现截屏功能
- QT实现截屏功能
- iphone 应用内部实现截屏功能
- Qt实现屏保功能,鼠标一定时间无响应程序进入待机状态
- C/C++ | Qt 实现爬虫功能,爬取CSDN博客文章
- Qt实现小功能之列表无限加载(创意很不错:监听滚动条事件,到底部的时候再new QListWidgetItem)
- Qt实现 二维码打印功能
- 关于Qt使用QNetworkAccessManager下载文件(实现断点续传功能)
- IOS中摇一摇实现截屏(可实现问题反馈的功能)
- C#实现QQ类似的截屏功能
- 一种基于Qt的可伸缩的全异步C/S架构服务器实现(六) 整合各个模块实现功能
- java实现截屏功能
- Android 视频播放器截屏功能实现讲解
- QT视图标尺功能实现(待补充)
- OpenG利用glreadPixel实现截屏功能
- Qt5.8《网络版够级》编写日志之五:客户端登陆及注册功能实现
- 利用QT实现截屏的四种方法
- Qt+MSVC使用libmodbus实现modbus主机功能