前言
在嵌入式仪器产品中,经常需要截取仪器界面图片,为相关技术或说明书等相关文档提供原材料;而使用命令行模式截屏的方式只适用于开发人员,针对这种情况便设计了该模块嵌入到仪器界面代码中,可完美解决该问题。
设计需求
在仪器上插入键盘,按下指定按键后可截下仪器当前界面(保存图片名为依次递增数字),且截屏不受界面限制,不管是否有弹窗或子界面等。按下第二个键可实现截图切换保存路劲(路径名最后数字+1),且图片名复位为从1开始递增。
设计思路
1、模块类继承QObject,并重写eventFilter(QObject *obj, QEvent *event)
函数;
2、识别功能按钮按下的事件,并运行截图程序;
3、截图程序,使用gsnp程序+输入参数方式实现(嵌入式linux下比较常见),当然也可以使用qt自带的QScreen类或其他众多方式保存截取。
4、安装事件过滤器,使用void installEventFilter(QObject *)
函数安装。
模块代码
h文件
class SreenCapture : public QObject
{
Q_OBJECT
public:
SreenCapture(){}
~SreenCapture(){}
bool eventFilter(QObject *obj, QEvent *event);
};
cpp文件
bool SreenCapture::eventFilter(QObject *obj, QEvent *event)
{
static QDateTime lastTime = QDateTime::currentDateTime();
if(event->type() == QEvent::KeyPress)
{
int timeCount = lastTime.secsTo(QDateTime::currentDateTime());
if(timeCount < 1)
return QObject::eventFilter(obj,event);
//qDebug()<<Q_FUNC_INFO<<"time count:"<<timeCount;
QKeyEvent *key=static_cast<QKeyEvent *>(event);
static int imgCount = 1,pathCount = 1;
if(key->key() == Qt::Key_F4)
{
imgCount = 0;
pathCount++;
if(pathCount > 100)
pathCount = 1;
}
if(key->key() == Qt::Key_F1)
{
QDir mntDir("/udisk");
if (!mntDir.exists()) //判断U盘是否插入
MessageBoxInstance::GetInstance()->warning(tr("提示"),tr("未识别到USB设备!"), 1,0);
else
{
QString imgPath = QString("/udisk/screen%1").arg(pathCount);
QDir buff(imgPath);
if(!buff.exists())
system("mkdir /udisk/screen");
imgPath += "/"+ QString::number(++imgCount) + ".jpg";
QString strCMD = QString("gsnap %1 /dev/fb0").arg(imgPath);
system(strCMD.toLatin1());
qDebug()<<tr("out img: ")+ imgPath;
//截图程序运行结束后添加提示(这里使用U盘图标闪烁一下表示截图结束)
StatusBarInstance::GetInstance()->SetUsbConnected(0);
for(int i = 0;i < 300;i ++)
{
usleep(1000);
qApp->processEvents();
}
StatusBarInstance::GetInstance()->SetUsbConnected(1);
}
}
lastTime = QDateTime::currentDateTime(); //记录最后一次截图时间
}
return QObject::eventFilter(obj,event);
}
使用方法
demo代码
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
SreenCapture *p = new SreenCapture();
a.installEventFilter(p);
return a.exec();
}
从demo中没找到MainWindow
或其他类的实现,所以该方式可实现无界面运行,即可独立一个程序执行,然后检测按键截取其他进程执行的界面。
注意
本模块SreenCapture
类的实现方式过于简单,其中只有一个虚函数,很多人就喜欢把他写在类中实现(默认为内联函数),这里编译器会报错误。因为类中如果有虚函数,那么至少要有一个函数在cpp文件中实现,否则编译的时候不会为该类创建虚函数表,从而会报undefine vtable的错误。