QTC++图形界面编程技术.docx
- 文档编号:28592356
- 上传时间:2023-07-19
- 格式:DOCX
- 页数:18
- 大小:20.95KB
QTC++图形界面编程技术.docx
《QTC++图形界面编程技术.docx》由会员分享,可在线阅读,更多相关《QTC++图形界面编程技术.docx(18页珍藏版)》请在冰豆网上搜索。
QTC++图形界面编程技术
通识教育课程论文
课程名称:
C++图形界面编程技术_
学院_
专业班级
学号
姓名爱尔兰(KEN
联系方式irelandken@
任课教师LZ
论QT的信号/槽机制
——WindowCut—一个简单实用的截图软件
在图形界面编程技术,我比较喜欢QT这个框架,喜欢它的一次编写,到处编译这种方式,既高效,移植性又强,我试过在window下用Qtcreator开发一个软件,然后直接将工程放到linuxubunto11.04下,再次用Qtcreator打开之前的工程,很简单地直接编译一次,一个代码也不用改,就将该软件移植到Linux下了,这一点很不错。
。
。
更重要的是,Qt为我们带来了全新的思想:
将一个工程逻辑分解为多个组件,利用强大的信号/槽机制,竟然可使这个工程分解为相互独立,互不干扰的若干个部分。
以下,我将通过介绍我的WindowCut截图软件的编写过程来分析这种思想。
界面:
截图过程:
截图后的效果:
思想:
这个软件由1:
主窗口mainWindow,2:
全屏截图器FullEditFEdit(就是半透明的全屏的组件)和3:
截图查看器PicSeePSee组成,这3部分都是互相独立的类,在类的定义中,类与类之间无直接的函数调用,这些组件定义了若干个signal/slot,而这3个类的实例是通过signal/slot机制偶合在一起的。
mainWindow上的Cut按键被按下后,mainWindow就隐藏,并发出一个StartCut()的信号,表示“开始截图”。
。
然后FEdit接收到StartCut()信号后,它就初始化,并记录下此时刻的屏幕背景,最后全屏显示半透明的背景。
。
。
然PSee接收这个信号后,它就隐藏起来。
。
当用户在全屏截图器FEdit的全屏半透明背景上选定好区域后,FullEdit就会隐藏窗口并发出FinishCut“截图完成”的信号(信号中包含了截图的地址),然后截图查看器PSee接收到FinishCut信号及其中的截图的地址后,就会显示窗口,并在窗口上面绘制截图显示给用户,而mainWindow收到FinishCut信号后,就会显示主窗口,并使save按钮可见。
此后,用户点击save按钮并成功保存后,mainWindow就会发出PicSaved“图片保存信号”,然后PSee会收到此信号,然后隐藏。
大概的流程就是这样。
软件的功能是简单的,但是,里面的思想却很有意义的。
对于mainWindow,它只管发射信号,压根儿不用知道有多少个对象收到这些信号(当然也不可能知道),并且当收到特定的信号时,就去执行信号处理器slot就可以了,FullEdit和PicSee也一样。
。
因为具体哪个信号与哪个槽有连接关系,不是在类的定义在确定的,而且信号/槽的连接是面向类的实例的(所以不可能由类的抽象或定义来确定),QObject:
:
connect(sender,SIGNAL,receiver,SLOT)这个函数要传递对象的实例作参数,所以无法对抽象(未实例化)的对象之间建立连接关系。
这些信号/槽的连接是在类外定义的(上述3个对象的连接关系是在main.cpp中面向这3个类的具体实例来定义的,与类的定义无关系)。
互相独立的组件+可靠的信号/槽机制=功能完善的软件
在一个项目中,假如我是PM,那么只要我们确定好项目中各组件的“信号/槽”连接关系后,我们就可以将这个项目分解为若干个相互独立,无不干扰的的部分,开发过程在只要严格尊守约定好的信号和槽就可以了,待各部分组件完成后,建立后组件的实例间的“信号/槽”关系好,这个项目就完成了。
。
。
嗯,这思想,这开发模式,不正是全世界开发者所追求的目标吗?
?
SRC:
main.cpp
#include
#include"widget.h"
#include"FullEdit.h"
#include"PicSee.h"
intmain(intargc,char*argv[])
{
QApplicationa(argc,argv);
WidgetmainWindow;//主窗口
FullEditFEdit;//全屏截图器
PicSeePSee;//截图后的截图查看器
//mainWindowtoPSee:
mainWindow发出StartCut信号后,PSee先最小化,然后再隐藏
QObject:
:
connect(&mainWindow,SIGNAL(StartCut()),&PSee,SLOT(Minimized_Hide()));
//mainWindowtoFEdit:
mainWindow发出StartCut信号后,FEdit先初始化再全屏显示
QObject:
:
connect(&mainWindow,SIGNAL(StartCut()),&FEdit,SLOT(Init_FCShow()));
////----------------------------------------------------------------
//当FEdit发出FinishCut信号时,mainWindow接收图片指针,并显示窗口(showNormal)
QObject:
:
connect(&FEdit,SIGNAL(FinishCut(QImage*)),&mainWindow,SLOT(Get_Pix_Show(QImage*)));
//当FEdit发出FinishCut信号时,PSee接收图片指针,并显示窗口(showNormal)
QObject:
:
connect(&FEdit,SIGNAL(FinishCut(QImage*)),&PSee,SLOT(Get_Pix_Show(QImage*)));
////----------------------------------------------------------------
//当FEdit发出CancleCut截图被取消的信号,mainWindow接收后就显示主窗口
QObject:
:
connect(&FEdit,SIGNAL(CancleCut()),&mainWindow,SLOT(showNormal()));
//mainWindowtoPSee:
mainWindow发出PicSaved图片保存信号后,PSee先最小化,然后再隐藏
QObject:
:
connect(&mainWindow,SIGNAL(PicSaved()),&PSee,SLOT(Minimized_Hide()));
mainWindow.show();
returna.exec();
}
////
widget.ui
////
widget.h
#ifndefWIDGET_H
#defineWIDGET_H
#include
namespaceUi{
classWidget;
}
classWidget:
publicQWidget
{
Q_OBJECT
public:
explicitWidget(QWidget*parent=0);
~Widget();
signals:
voidStartCut();//表示开始截图的信号
voidPicSaved();//图片成功保存的信号
publicslots:
//收到FinishCut信号时,mainWindow接收图片指针,并显示窗口(showNormal)
voidGet_Pix_Show(QImage*final_pix);
privateslots:
voidon_CutButton_clicked();
voidon_SaveButton_clicked();
private:
Ui:
:
Widget*ui;
QImagefinal_pix;//最终的截图
};
#endif//WIDGET_H
////
widget.ccp
#include"widget.h"
#include"ui_widget.h"
#include
#include
#include"FullEdit.h"
Widget:
:
Widget(QWidget*parent):
QWidget(parent),
ui(newUi:
:
Widget)
{
ui->setupUi(this);
this->setFixedSize(265,90);
this->setWindowTitle("WindowCutRC3.1");
}
Widget:
:
~Widget()
{
deleteui;
}
/**
按钮Cut被按下后,截图查看器PSee隐藏,主窗口隐藏,然后调用全屏截图器FEdit的init()来获得
当前窗口的背景,并全屏显示
*/
voidWidget:
:
on_CutButton_clicked()
{
this->showMinimized();
this->hide();
emitStartCut();//发出开始截图StartCut信号
}
/**
保存按钮按下后,选择保存的位置,然后保存,保存成功后,截图查看器PSee隐藏,否则发出warning
*/
voidWidget:
:
on_SaveButton_clicked()
{
QStringsaveName=QFileDialog:
:
getSaveFileName
(this,tr("SaveFile"),"/",
tr("BMPFile(*.BMP);;PNGFile(*.PNG);;JPEGFile(*.JPG)"));
if(saveName.isNull())//没有选择路径,则返回主窗口
return;
if(final_pix.save(saveName))
emitPicSaved();////图片成功保存的信号
else
QMessageBox:
:
warning(this,"SaveError","SaveError");
}
/**
Get_Pix()是下个SLOT,当FEdit发出Send_Pix信号时,主窗口就用Get_Pix来接收发出的图片指针
然后Enable保存按钮,显示主窗口,
然后将此图片的指针发给截图查看器PSee,并在截图查看器PSee显示此图片
*/
voidWidget:
:
Get_Pix_Show(QImage*final_pix)
{
this->final_pix=*final_pix;//接收发出的图片指针
ui->SaveButton->setEnabled(true);//这里可保存了,则使保存按钮显示
this->showNormal();//
}
////
FullEdit.h
#ifndefFULLEDIT_H
#defineFULLEDIT_H
#include
classQPixmap;
classFullEdit:
publicQWidget
{
Q_OBJECT
public:
explicitFullEdit(QWidget*parent=0);
QImageConverToShadow(QImagepix);//将原图转换为半透明的图片
//从原图pre在载取坐标(x1,y1),(x2,y2)所包围的部分区域的图片
QImage_Cut(QImagepre,intx1,inty1,intx2,inty2);
signals:
voidFinishCut(QImage*final_pix);//当用户释放左键时,用signal发送图片的指针
voidCancleCut();//当用户在FullEdit上单击左键时,发出截图取消信号
publicslots:
//收到StartCut信号后,FullEdit先初始化,记录下此时刻的屏幕背景,并全屏显示
voidInit_FCShow();
protected:
voidmousePressEvent(QMouseEvent*);
voidmouseMoveEvent(QMouseEvent*);
voidmouseReleaseEvent(QMouseEvent*);
voidpaintEvent(QPaintEvent*);
private:
QImage_screen;//存放当前的全屏的截图
QImage_shadow;//存放当前全屏截图的半透明的幅本
intx1,y1,x2,y2;//当前选定区域的两角的坐标
boolisLeftDown;//记录当前左键是否被按下
};
#endif//FULLEDIT_H
////
FullEdit.cpp
#include"FullEdit.h"
#include
#include
#include
#include
//#include
//#definemyDebug
#ifdefmyDebug
#include
#include
#endif
FullEdit:
:
FullEdit(QWidget*parent):
QWidget(parent)
{
//omp_set_num_threads(omp_get_max_threads());
#ifdefmyDebug
qDebug()<<"omp_get_max_threads():
"< qDebug()<<"omp_get_num_threads(): "< #endif } //收到StartCut信号后,FEdit先初始化再全屏显示 voidFullEdit: : Init_FCShow()//初始化,并记录下此时刻的屏幕背景 { //取得当前全屏的窗口 _screen=QPixmap: : grabWindow(QApplication: : desktop()->winId()).toImage(); //取得当前全屏截图的半透明的幅本 _shadow=ConverToShadow(_screen); //位置"左键被按下"的标志 isLeftDown=false; this->showFullScreen();//全屏显示 } /** 将原图转换为半透明的图片 原理: 取得原图pix转换为QImage: : Format_ARGB32格式的副本 此时得到的副本每个像素的格式为0xAARRGGBB 其alpha通道AA一定==FF(255) 然后我们将alpha通道改为(127),这样得到的就是半透明的效果 */ QImageFullEdit: : ConverToShadow(QImagepix) { //取得原图pix转换为QImage: : Format_ARGB32格式的副本 QImagetmp=pix.convertToFormat(QImage: : Format_ARGB32); intw=tmp.width(); inth=tmp.height(); //处理每一个像素 //#pragmaompparallelfor for(inti=0;i for(intj=0;j { QRgbcol=QRgb((tmp.pixel(i,j)<<1)>>1);//将a通道设为127 tmp.setPixel(i,j,col); } returntmp; } ///////// template inlinevoidswap(T&a,T&b) { a^=b; b^=a; a^=b; } /** //从原图pre在载取坐标(x1,y1),(x2,y2)所包围的部分区域的图片 就是建一个QImage对像,其大小就是截图区域的大小, 然后向这个对像中填充原图中对应的像素就可以了 */ inlineQImageFullEdit: : _Cut(QImagepre,int_x1,int_y1,int_x2,int_y2) { #ifdefmyDebug clock_tt=-clock(); #endif if(_x1>_x2)swap(_x1,_x2); if(_y1>_y2)swap(_y1,_y2);//使(x1,y1)为left-top坐标,(x2,y2)为right-bottom坐标 inth=_x2-_x1; intw=_y2-_y1; QImagetmp(h,w,QImage: : Format_RGB32); QRgbcol; //#pragmaompparallelfor for(intx=0;x for(inty=0;y { col=pre.pixel(_x1+x,_y1+y); tmp.setPixel(x,y,col); } #ifdefmyDebug t+=clock(); qDebug()<<"t: "< #endif returntmp; } /** 左键被按下,记录起始坐标记录当前左键是被按下 如果是右键的话,通常就是想放弃截图,所以隐藏全屏截图器FullEdit, 然后发出窗口已隐藏的信号来通知主窗口 */ voidFullEdit: : mousePressEvent(QMouseEvent*event) { if(event->button()==Qt: : LeftButton)//左键被按下,记录起始坐标 { x1=event->pos().x(); y1=event->pos().y(); isLeftDown=true;////记录当前左键是否被按下 } else//右键被按下,则放弃截图并退出 { this->hide(); emitCancleCut();//发出CancleCut取消截图信号 } } voidFullEdit: : mouseMoveEvent(QMouseEvent*event) { if(event->buttons()&Qt: : LeftButton)//左键被按下 { x2=event->pos().x(); y2=event->pos().y(); update();//截图区域被改变,则重绘窗口 } } /** 如果左键被释放,则用QImage对像记录截图区域,隐藏当前窗口,然后用信号机制将这个对象的指针发出 */ voidFullEdit: : mouseReleaseEvent(QMouseEvent*event) { if(event->button()==Qt: : LeftButton) { isLeftDown=false;////记录当前左键是否被按下,这里是"否" x2=event->pos().x(); y2=event->pos().y();//记录截图区域的对角的坐标 if(x1>x2)swap(x1,x2); if(y1>y2)swap(y1,y2);//使(x1,y1)为left-top坐标,(x2,y2)为right-bottom坐标 //记录截图区域 QImage*_final_screen=newQImage(this->_Cut(_screen,x1,y1,x2,y2)); this->hide();//截图完成后,使这个窗口设为hide emitFinishCut(_final_screen);//当用户释放左键时,发出FinishCut截图完成信号 } } /** 全屏截图器的重绘,就是先绘制半透明背景, 然后从原背景中cut一个当前选中的区域,并绘在半透明背景的上方 再绘出蓝色边框包围起截图的区域,用于提示 */ voidFullEdit: : paintEvent(QPaintEvent*) { QPainterpaint(this); //绘制半透明背景 paint.drawImage(0,0,_shadow); if(isLeftDown) { //从原背景中cut一个当前选中的区域,并绘在半透明背景的上方 QImagetmp=this->_Cut(_screen,x1,y1,x2,y2); intlx=(x1<=x2)? x1: x2; intly=(y1<=y2)? y1: y2; paint.drawImage(lx,ly,tmp); // //用蓝色边框包围起截图的区域 QPenmyPen; myPen.setWidth (1); myPen.setColor(Qt: : blue); paint.setPen(myPen); paint.drawLine(x1,y1,x1,y2); paint.drawLine(x1,y1,x2,y1); paint.drawLine(x1,y2,x2,y2); paint.drawLine(x2,y1,x2,y2); // } } //// PicSee.h #ifndefPICSEE_H #definePICSEE_H #include classPicSee: publicQWidget { Q_OBJECT public: explicitPicSee(QWidget*parent=0); publicslots: voidMinimized_Hide();//收到StartCut信号后,先最小化,然后再隐藏 //收到FinishCut,PSee接收图片指针,并显示窗口(showNormal) voidGet_Pix_Show(QImage*final_pix); protected: voidpaintEvent(QPaintEvent*); private: QImage*_pix; }; #endif//PICSEE_H
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- QTC 图形界面 编程 技术