《QTC++图形界面编程技术.doc》由会员分享,可在线阅读,更多相关《QTC++图形界面编程技术.doc(18页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、/ 通识教育课程论文 课程名称: C+图形界面编程技术 _ 学 院 _ 专业班级 学 号 姓 名 爱尔兰(KEN 联系方式 任课教师 LZ 论QT的信号/槽机制WindowCut一个简单实用的截图软件在图形界面编程技术,我比较喜欢QT这个框架,喜欢它的一次编写,到处编译这种方式,既高效,移植性又强,我试过在window下用Qt creator开发一个软件,然后直接将工程放到linux ubunto 11.04下,再次用Qt creator打开之前的工程,很简单地直接编译一次,一个代码也不用改,就将该软件移植到Linux下了,这一点很不错。更重要的是,Qt为我们带来了全新的思想:将一个工程逻辑
2、分解为多个组件,利用强大的信号/槽机制,竟然可使这个工程分解为相互独立,互不干扰的若干个部分。以下,我将通过介绍我的WindowCut截图软件的编写过程来分析这种思想。界面:截图过程:截图后的效果:思想:这个软件由 1:主窗口mainWindow,2:全屏截图器 FullEdit FEdit(就是半透明的全屏的组件) 和 3:截图查看器 PicSee PSee 组成,这3部分都是互相独立的类,在类的定义中,类与类之间无直接的函数调用,这些组件定义了若干个signal/slot, 而这3个类的实例是通过 signal/slot机制偶合在一起的。mainWindow上的Cut按键被按下后,main
3、Window就隐藏,并发出一个StartCut()的信号,表示“开始截图”。然后FEdit接收到StartCut()信号后,它就初始化,并记录下此时刻的屏幕背景,最后全屏显示半透明的背景。然PSee接收这个信号后,它就隐藏起来。当用户在全屏截图器FEdit的全屏半透明背景上选定好区域后,FullEdit就会隐藏窗口并发出FinishCut“截图完成”的信号(信号中包含了截图的地址),然后截图查看器PSee接收到FinishCut信号及其中的截图的地址后,就会显示窗口,并在窗口上面绘制截图显示给用户,而mainWindow收到FinishCut信号后,就会显示主窗口,并使save按钮可见。此后,
4、用户点击save按钮并成功保存后,mainWindow就会发出PicSaved“图片保存信号”,然后PSee会收到此信号,然后隐藏。大概的流程就是这样。软件的功能是简单的,但是,里面的思想却很有意义的。对于mainWindow,它只管发射信号,压根儿不用知道有多少个对象收到这些信号(当然也不可能知道),并且当收到特定的信号时,就去执行信号处理器slot就可以了,FullEdit 和 PicSee也一样。因为具体哪个信号与哪个槽有连接关系,不是在类的定义在确定的,而且信号/槽的连接是面向类的实例的(所以不可能由类的抽象或定义来确定),QObject: connect (sender, SIGNA
5、L,receiver,SLOT)这个函数要传递对象的实例作参数,所以无法对抽象(未实例化)的对象之间建立连接关系。这些信号/槽的连接是在类外定义的(上述3个对象的连接关系是在main.cpp中面向这3个类的具体实例来定义的,与类的定义无关系)。互相独立的组件+ 可靠的信号/槽机制 功能完善的软件在一个项目中,假如我是PM,那么只要我们确定好项目中各组件的“信号/槽”连接关系后,我们就可以将这个项目分解为若干个相互独立,无不干扰的的部分,开发过程在只要严格尊守约定好的信号和槽就可以了,待各部分组件完成后,建立后组件的实例间的“信号/槽”关系好,这个项目就完成了。嗯,这思想,这开发模式,不正是全世
6、界开发者所追求的目标吗?SRC:main.cpp#include #include widget.h#include FullEdit.h#include PicSee.hint main(int argc, char *argv) QApplication a(argc, argv); Widget mainWindow; /主窗口FullEdit FEdit; /全屏截图器PicSee PSee; /截图后的截图查看器/mainWindow to PSee:mainWindow发出StartCut信号后,PSee先最小化,然后再 隐藏QObject:connect(&mainWindow,
7、SIGNAL(StartCut(),&PSee,SLOT(Minimized_Hide();/mainWindow to FEdit:mainWindow发出StartCut信号后,FEdit先初始化再全屏显示QObject:connect(&mainWindow,SIGNAL(StartCut(),&FEdit,SLOT(Init_FCShow();/-/当FEdit发出FinishCut信号时,mainWindow接收图片指针,并显示窗口(showNormal)QObject:connect(&FEdit,SIGNAL(FinishCut(QImage *),&mainWindow,SLO
8、T(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();/mainWindow to PSee:m
9、ainWindow发出PicSaved图片保存信号后,PSee先最小化,然后再 隐藏QObject:connect(&mainWindow,SIGNAL(PicSaved(),&PSee,SLOT(Minimized_Hide(); mainWindow.show(); return a.exec();/widget.ui/widget.h#ifndef WIDGET_H#define WIDGET_H#include namespace Ui class Widget;class Widget : public QWidget Q_OBJECTpublic: explicit Widget(
10、QWidget *parent = 0); Widget();signals:void StartCut();/表示开始截图的信号void PicSaved();/图片成功保存的信号public slots: /收到FinishCut信号时,mainWindow接收图片指针,并显示窗口(showNormal) void Get_Pix_Show(QImage *final_pix);private slots: void on_CutButton_clicked(); void on_SaveButton_clicked();private: Ui:Widget *ui; QImage fin
11、al_pix; /最终的截图;#endif / WIDGET_H/widget.ccp#include widget.h#include ui_widget.h#include #include#include FullEdit.hWidget:Widget(QWidget *parent) : QWidget(parent), ui(new Ui:Widget) ui-setupUi(this); this-setFixedSize(265,90);this-setWindowTitle(WindowCut RC 3.1);Widget:Widget() delete ui;/*按钮Cut被
12、按下后,截图查看器PSee隐藏,主窗口隐藏,然后调用全屏截图器FEdit的init()来获得当前窗口的背景,并全屏显示*/void Widget:on_CutButton_clicked()this-showMinimized(); this-hide();emit StartCut(); /发出开始截图StartCut信号/*保存按钮按下后,选择保存的位置,然后保存,保存成功后,截图查看器PSee隐藏,否则发出warning*/void Widget:on_SaveButton_clicked() QString saveName = QFileDialog:getSaveFileName
13、(this, tr(Save File),/,tr(BMP File(*.BMP); PNG File(*.PNG); JPEG File(*.JPG); if(saveName.isNull() /没有选择路径,则返回主窗口 return; if(final_pix.save(saveName)emit PicSaved(); /图片成功保存的信号 else QMessageBox:warning(this,Save Error,Save Error);/*Get_Pix() 是下个SLOT,当FEdit发出Send_Pix信号时,主窗口就用Get_Pix来接收发出的图片指针然后Enable
14、保存按钮,显示主窗口,然后将此图片的指针发给截图查看器PSee,并在截图查看器PSee显示此图片*/void Widget:Get_Pix_Show(QImage *final_pix) this-final_pix = *final_pix; /接收发出的图片指针ui-SaveButton-setEnabled(true); /这里可保存了,则使保存按钮显示this-showNormal();/FullEdit.h#ifndef FULLEDIT_H#define FULLEDIT_H#include class QPixmap;class FullEdit : public QWidget
15、 Q_OBJECTpublic: explicit FullEdit(QWidget *parent = 0); QImage ConverToShadow(QImage pix); /将原图转换为半透明的图片 /从原图pre在载取坐标(x1,y1),(x2,y2)所包围的部分区域的图片 QImage _Cut(QImage pre,int x1,int y1,int x2,int y2);signals: void FinishCut(QImage *final_pix); /当用户释放左键时,用signal发送图片的指针void CancleCut(); /当用户在FullEdit上单击左
16、键时,发出截图取消信号public slots:/收到StartCut信号后,FullEdit先初始化,记录下此时刻的屏幕背景,并全屏显示void Init_FCShow(); protected: void mousePressEvent(QMouseEvent *); void mouseMoveEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); void paintEvent(QPaintEvent *);private: QImage _screen; /存放当前的全屏的截图 QImage _shadow; /存放当
17、前全屏截图的半透明的幅本 int x1,y1,x2,y2; /当前选定区域的两角的坐标 bool isLeftDown; /记录当前左键是否被按下;#endif / FULLEDIT_H/FullEdit.cpp#include FullEdit.h#include#include#include#include/#include/#define myDebug#ifdef myDebug#include#include#endifFullEdit:FullEdit(QWidget *parent): QWidget(parent)/omp_set_num_threads(omp_get_ma
18、x_threads();#ifdef myDebugqDebug()omp_get_max_threads(): omp_get_max_threads();qDebug()omp_get_num_threads(): winId().toImage();/取得当前全屏截图的半透明的幅本 _shadow = ConverToShadow(_screen);/位置左键被按下的标志 isLeftDown = false;this-showFullScreen(); /全屏显示/*将原图转换为半透明的图片原理: 取得原图pix转换为QImage:Format_ARGB32格式的副本此时得到的副本每个
19、像素的格式为 0xAARRGGBB其alpha通道 AA 一定 = FF(255)然后我们将alpha通道改为(127),这样得到的就是半透明的效果 */QImage FullEdit:ConverToShadow(QImage pix)/取得原图pix转换为QImage:Format_ARGB32格式的副本 QImage tmp = pix.convertToFormat(QImage:Format_ARGB32); int w = tmp.width(); int h = tmp.height();/处理每一个像素/#pragma omp parallel for for(int i=0;
20、 iw; i+) for(int j=0; jh; j+) QRgb col = QRgb(tmp.pixel(i,j)1); /将a通道设为127 tmp.setPixel(i,j,col); return tmp;/template inline void swap(T &a, T &b) a = b; b = a; a = b;/*/从原图pre在载取坐标(x1,y1),(x2,y2)所包围的部分区域的图片就是建一个QImage对像,其大小就是截图区域的大小,然后向这个对像中填充原图中对应的像素就可以了*/inline QImage FullEdit:_Cut(QImage pre,in
21、t _x1,int _y1,int _x2,int _y2)#ifdef myDebugclock_t t = -clock();#endif if(_x1 _x2) swap(_x1,_x2); if(_y1 _y2) swap(_y1,_y2); /使(x1,y1)为left-top坐标, (x2,y2)为right-bottom坐标 int h = _x2 - _x1; int w = _y2 - _y1; QImage tmp(h,w,QImage:Format_RGB32); QRgb col;/#pragma omp parallel for for(int x=0; xh; x+
22、) for(int y=0; yw; y+) col = pre.pixel(_x1+x,_y1+y); tmp.setPixel(x,y,col); #ifdef myDebugt += clock();qDebug()t: button() = Qt:LeftButton) /左键被按下,记录起始坐标 x1 = event-pos().x(); y1 = event-pos().y(); isLeftDown = true; /记录当前左键是否被按下 else /右键被按下,则放弃截图并退出this-hide();emit CancleCut(); /发出CancleCut取消截图信号 v
23、oid FullEdit:mouseMoveEvent(QMouseEvent *event) if(event-buttons() & Qt:LeftButton) /左键被按下 x2 = event-pos().x(); y2 = event-pos().y(); update(); /截图区域被改变,则重绘窗口 /*如果左键被释放,则用QImage对像记录截图区域,隐藏当前窗口,然后用信号机制将这个对象的指针发出*/void FullEdit:mouseReleaseEvent(QMouseEvent *event)if(event-button() = Qt:LeftButton)is
24、LeftDown = 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 = new QImage(this-_Cut(_screen,x1,y1,x2,y2);this-hide(); /截图完成后,使这个窗口设为hideemit FinishCut(_f
25、inal_screen); /当用户释放左键时,发出FinishCut截图完成信号/*全屏截图器的重绘,就是先绘制半透明背景,然后从原背景中cut一个当前选中的区域,并绘在半透明背景的上方再绘出蓝色边框包围起截图的区域,用于提示*/void FullEdit:paintEvent(QPaintEvent *) QPainter paint(this);/绘制半透明背景 paint.drawImage(0,0,_shadow); if(isLeftDown) /从原背景中cut一个当前选中的区域,并绘在半透明背景的上方 QImage tmp = this-_Cut(_screen,x1,y1,x
26、2,y2); int lx = (x1=x2)? x1:x2; int ly = (y1=y2)? y1:y2; paint.drawImage(lx,ly,tmp); /用蓝色边框包围起截图的区域QPen myPen;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#if
27、ndef PICSEE_H#define PICSEE_H#include class PicSee : public QWidget Q_OBJECTpublic: explicit PicSee(QWidget *parent = 0);public slots:void Minimized_Hide(); /收到StartCut信号后,先最小化,然后再 隐藏/收到FinishCut,PSee接收图片指针,并显示窗口(showNormal) void Get_Pix_Show(QImage *final_pix); protected: void paintEvent(QPaintEven
28、t *);private: QImage *_pix;#endif / PICSEE_H/PicSee.cpp#include PicSee.h#includePicSee:PicSee(QWidget *parent): QWidget(parent)this-setWindowTitle(WindowCut RC 3.1);void PicSee:paintEvent(QPaintEvent *) QPainter painter(this); painter.drawImage(0,0,*_pix);void PicSee:Minimized_Hide() /收到StartCut信号后,先最小化,然后再 隐藏this-showMinimized();this-hide();void PicSee:Get_Pix_Show(QImage *final_pix)this-_pix = final_pix;this-setFixedSize(_pix-size(); /将此图片的指针发给截图查看器PSeethis-showNormal(); /在截图查看器PSee显示此图片/