首先在这里感谢刘大师,提供的源码进行学习。如有冒犯之意,请联系我将其删除,谢谢!这是刘大师的个人主页.
目前跟随刘大师的脚步,学习了一下采用Qt实现截图的效果,具体效果如下:
废话不多说,先谈谈这个功能。
首先我们了解一下这个截图:首先,我们是点击“截图工具“,然后弹出灰色的背景,在拖动鼠标进行截图,最后在保存图片。
截屏思想:点击截屏工具的时候,截取全屏的像素,并且将全屏保存到一个全局的变量pixmap中。然后,在点击鼠标移动,截取一个相应的矩形。将其绘制出来。然后在保存。。
那么接下来就可以贴上源码进行解释了:
void frmAPI::on_btnScreenAPI_clicked()
{
frmScreen::Instance()->showFullScreen();//显示全屏widget
}
这个是点击截图工具以后实现的槽函数。showFllScreen() –> 将widget全屏显示(于是就有了点击以后全屏变灰色)。接着便是调用frmScreen的回调函数
frmScreen::frmScreen(QWidget *parent) : QDialog(parent)
{
this->initForm();
}
//初始化框架
void frmScreen::initForm()
{
this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);//隐藏标题栏,窗体出现在最顶层
menu = new QMenu(this);
menu->addAction("保存截图", this, SLOT(saveScreen()));
menu->addAction("截图另存为", this, SLOT(saveScreenOther()));
menu->addAction("全屏截图", this, SLOT(saveFullScreen()));
menu->addAction("退出截图", this, SLOT(hide()));
//取得屏幕大小
qDebug()<<QApplication::desktop()->size();
screen = new ScreenAPI(QApplication::desktop()->size());
//保存全屏图像
fullScreen = new QPixmap();
}
初始化这里先创建了一个对象ScreenAPI。这个对象便是实现屏幕API的一个类。该类定义如下:这是一个纯C++定义的一个类。(没有Q_OBJECT)
class ScreenAPI
{
public:
enum STATUS {SELECT, MOV, SET_W_H};
ScreenAPI() {}
ScreenAPI(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 移动截图区域
private:
QPoint leftUpPos, rightDownPos; //记录 截图区域 左上角、右下角
QPoint startPos, endPos; //记录 鼠标开始位置、结束位置
int maxWidth, maxHeight; //记录屏幕大小
STATUS status; //三个状态: 选择区域、移动区域、设置width height
void cmpPoint(QPoint &s, QPoint &e);//比较两位置,判断左上角、右下角
};
具体构造函数如下。
ScreenAPI::ScreenAPI(QSize size)
{
maxWidth = size.width();//获得整个屏幕的大小
maxHeight = size.height();
startPos = QPoint(-1, -1);//开始坐标
endPos = startPos;//结束坐标
leftUpPos = startPos;//左上角坐标
rightDownPos = startPos;//右下角坐标
status = SELECT;
}
由于在.h文件中重写了 void showEvent(QShowEvent )事件,因此在显示窗体的时候,会被调用。并且重写了void paintEvent(QPaintEvent );事件重绘函数,因此也会被调用一次。
//显示窗口Widget发出事件被调用
void frmScreen::showEvent(QShowEvent *)
{
QPoint point(-1, -1);
screen->setStart(point);//设置开启坐标点
screen->setEnd(point);//设置结束坐标点
//全屏图像,抓取窗体
*fullScreen = QPixmap::grabWindow(QApplication::desktop()->winId(), 0, 0, screen->width(), screen->height());
//设置透明度实现模糊背景
QPixmap pix(screen->width(), screen->height());
pix.fill((QColor(160, 160, 160, 200)));//模糊颜色填充
bgScreen = new QPixmap(*fullScreen);
QPainter p(bgScreen);
p.drawPixmap(0, 0, pix);
}
//重绘事件 update调用
void frmScreen::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(Qt::green);
pen.setWidth(2);
pen.setStyle(Qt::DotLine);//虚线样式
painter.setPen(pen);
QFont font;
font.setFamily("Microsoft YaHei");
font.setPointSize(10);
painter.setFont(font);
//截屏思想:点击截屏工具的时候,截取全屏的像素,并且将全屏保存到一个全局的变量pixmap中。
//然后,在点击鼠标移动,截取一个相应的矩形。将其绘制出来。
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);//绘制截图矩形
pen.setColor(Qt::yellow);
painter.setPen(pen);
painter.drawText(x + 2, y - 8, tr("截图范围:( %1 x %2 ) - ( %3 x %4 ) 图片大小:( %5 x %6 )")
.arg(x).arg(y).arg(x + w).arg(y + h).arg(w).arg(h));
}
接下来便是点击鼠标,移动鼠标,释放鼠标的几个重写事件了。
//鼠标按下事件
void frmScreen::mousePressEvent(QMouseEvent *e)
{
int status = screen->getStatus();//获取状态
if (status == ScreenAPI::SELECT) {
screen->setStart(e->pos());
} else if (status == ScreenAPI::MOV) {
if (screen->isInArea(e->pos()) == false) {
screen->setStart(e->pos());
screen->setStatus(ScreenAPI::SELECT);
} else {
movPos = e->pos();
this->setCursor(Qt::SizeAllCursor);
}
}
update();
}
//鼠标移动事件
void frmScreen::mouseMoveEvent(QMouseEvent *e)
{
if (screen->getStatus() == ScreenAPI::SELECT) {//选择区域
screen->setEnd(e->pos());//得到结束点坐标
} else if (screen->getStatus() == ScreenAPI::MOV) {//移动区域
QPoint p(e->x() - movPos.x(), e->y() - movPos.y());
screen->move(p);
movPos = e->pos();
}
update();
}
//鼠标释放事件
void frmScreen::mouseReleaseEvent(QMouseEvent *)
{
if (screen->getStatus() == ScreenAPI::SELECT) {
screen->setStatus(ScreenAPI::MOV);
} else if (screen->getStatus() == ScreenAPI::MOV) {
this->setCursor(Qt::ArrowCursor);
}
}
到此,就实现了这个功能。