QT基础学习知识整理

上传人:沈*** 文档编号:72129459 上传时间:2022-04-08 格式:DOC 页数:25 大小:922KB
收藏 版权申诉 举报 下载
QT基础学习知识整理_第1页
第1页 / 共25页
QT基础学习知识整理_第2页
第2页 / 共25页
QT基础学习知识整理_第3页
第3页 / 共25页
资源描述:

《QT基础学习知识整理》由会员分享,可在线阅读,更多相关《QT基础学习知识整理(25页珍藏版)》请在装配图网上搜索。

1、QT基础学习知识整理1. 重要内容:1) 信号和槽机制2) 事件处理机制3) 布局管理器4) 绘图5) 网络6) 多线程7) 其他(定时器,中文显示)2.1 一个简单的例子不可免俗的,从最简单的基本窗口产生开始介绍,窗口标题就叫作First Qt!好了,请新增一个目录hello,并在当中使用任一编辑器来编辑一个hello.cpp的档案,内容如下: hello.cpp #include #include int main(int argc, char *argv) QApplication app(argc, argv); QLabel *label = new QLabel(Hello!Wor

2、ld! Orz.); label-setWindowTitle(First Qt!); label-resize(200, 50); label-show(); return app.exec();要使用Qt的组件,必须含入(include)相对应的头文件,程序的第一行包含的QApplication与Qlabel头文件,稍后才可以使用QApplication与QLabel两个组件的定义类别。 每个Qt窗口程序,都必须有且只能有一个QApplication对象,它管理了整个应用程序所需的资源,QLabel是Qt的图型组件之一,继承自 QWidget,Widget这个名称来自Window Gadg

3、et,表示可视的使用者接口组件,可接受使用者的动作操作,文字画面、按钮、滚动条、工具列甚至容器(Container)等都是一种 Widget。 C+程序从main开始,再来进行Qt组件的初始化动作,在第一行中:QApplication app(argc, argv);QApplication负责程序的初始、结束及处理事件(event)的循环等,并提供基本的窗口外观,这个外观与系统的桌面环境有关,例如标题列的样式、窗口外观、系统功能键等,在不同的操作系统桌面环境下,会有各自不同的外观,QApplication 对象接受命令列自变量作为它的自变量,像是如果您没有设定窗口标题,且会使用执行文件的名称

4、作为窗口标题名称,可以使用的自变量与其作用,可以查询Qt在线文件关于QApplication类别的说明。 接着建立QLabel组件,它用以显示所指定的文字(在这边指定了Hello!World! Orz.),setWindowTitle()用以设定窗口标题,如果不设定标题,则会自动以程序的文件名称作为标题,resize()方法用以设定组件的长、宽,单位是像素(Pixel),Qt的组件预设是不可视的,所以要使用show()方法将之显示出来。在最后一行,执行QApplication的exec()方法,这将程序的控制权交给了QApplication,exec()方法会提供一个事件处理循环,窗口显示之后

5、会不断倾听(listen)事件,像是键盘、鼠标等动作所引发的事件, 写好程序存盘之后,就可以开始进行make的动作,必须先产生Makefile,Qt提供了qmake程序来协助建立Makefile,它可以自动根据目前目录下档案产生*.pro的专案档(project file):qmake -project然后根据项目档产生Makefile:qmake 接下来就可以进行make: make make完成之后,可以在debug目录下找到产生的hello.exe档案,直接执行:hello如果您要可以在Windows下直接double click就执行程序,记得系统环境变量中要设定PATH包括Qt安装目

6、录下的bin目录,执行时的参考画面如下所示:如果要建构release版本,则使用make时指定-f与Makefile名称,例如:make -f Makefile.Release则您可以在release数据夹下看到建构好的档案。QLabel支持HTML卷标,如果您把程序改为以下的内容:#include #include int main(int argc, char *argv) QApplication app(argc, argv); QLabel *label = new QLabel( Hello!World!Orz.); label-setWindowTitle(First Qt!);

7、 label-resize(200, 50); label-show(); return app.exec();重新建置之后,执行结果将显示如下:2.2信号和槽机制信号和槽用于对象间的通讯。信号/槽机制是Qt的一个中心特征并且也许是Qt与其它框架非常不同的核心特性。 在图形用户界面编程中,我们经常希望一个窗口部件的一个变化被通知给另一个窗口部件。更一般地,我们希望任何一类的对象可以和其它对象进行通讯。例如,如果我们正在解析一个XML文件,当我们遇到一个新的标签时,我们也许希望通知列表视图我们正在用来表达XML文件的结构。较老的工具包使用一种被称作回调的通讯方式来实现同一目的。回调是指一个函数的

8、指针,所以如果你希望一个处理函数通知你一些事件,你可以把另一个函数(回调)的指针传递给处理函数。处理函数在适当的时候调用回调。回调有两个主要缺点。首先他们不是类型安全的。我们从来都不能确定处理函数使用了正确的参数来调用回调。其次回调和处理函数是非常强有力地联系在一起的,因为处理函数必须知道要调用哪个回调。一个关于一些信号和槽连接的摘要图在Qt中我们有一种可以替代回调的技术。我们使用信号和槽。当一个特定事件发生的时候,一个信号被发射。Qt的窗口部件有很多预定义的信号,但是我们总是可以通过继承来加入我们自己的信号。槽就是一个可以被调用处理特定信号的函数。Qt的窗口部件又很多预定义的槽,但是通常的习

9、惯是你可以加入自己的槽,这样你就可以处理你所感兴趣的信号。信号和槽的机制是类型安全的:一个信号的签名必须与它的接收槽的签名相匹配。(实际上一个槽的签名可以比它接收的信号的签名少,因为它可以忽略额外的签名。)因为签名是一致的,编译器就可以帮助我们检测类型不匹配。信号和槽是宽松地联系在一起的:一个发射信号的类不用知道也不用注意哪个槽要接收这个信号。Qt的信号和槽的机制可以保证如果你把一个信号和一个槽连接起来,槽会在正确的时间使用信号的参数而被调用。信号和槽可以使用任何数量、任何类型的参数。它们是完全类型安全的:不会再有回调核心转储(core dump)。从QObject类或者它的一个子类(比如QW

10、idget类)继承的所有类可以包含信号和槽。当对象改变它们的状态的时候,信号被发送,从某种意义上讲,它们也许对外面的世界感兴趣。这就是所有的对象通讯时所做的一切。它不知道也不注意无论有没有东西接收它所发射的信号。这就是真正的信息封装,并且确保对象可以用作一个软件组件。例子以下的例子将看到有参数的Signal发送及Slot接受,并也将介绍Qt组件的parent/child关系,这个程序将建立一个LCD数字显示组件,以及一个拉杆组件,LCD数字将反应目前拉杆的进度:#include #include #include #include int main(int argc, char *argv)

11、QApplication app(argc, argv); QWidget *parent = new QWidget; parent-setWindowTitle(Signal & Slot); parent-setMinimumSize(240, 140); parent-setMaximumSize(240, 140); QLCDNumber *lcd = new QLCDNumber(parent); lcd-setGeometry(70, 20, 100, 30); QSlider *slider = new QSlider(Qt:Horizontal, parent); slide

12、r-setRange(0, 99); slider-setValue(0); slider-setGeometry(70, 70, 100, 30); QObject:connect(slider, SIGNAL(valueChanged(int), lcd, SLOT(display(int); parent-show(); return app.exec();在Qt中建立Widget时,要建立在heap区(即以new的方式),Qt会自动管理parent下child的delete,让您不用亲自管理具有parent/child关系的Widget建构与删除,这可以避免memory leak,您要

13、delete的只有那些没有parent的对象,如果您将对象建立在stack区,程序将可能会有错误发生。 QWidget是Qt中所有使用者图形接口组件的父类别,可在屏幕上绘制自身,可接受鼠标、键盘等接口操作,一个QWidget可以指定它的parent 为哪个组件,而这也表示child可显示的范围将是在parent之内,parent没有显示的话,子组件也不会显示。没有指定parent的QWidget是一个独立窗口(window)。在程序中建立了一个QWidget实例,并设定它的标题名称,以及可拉动的最大(setMaximumSize)最小(setMinimumSize)尺寸,由于都设定为240X1

14、40像素大小,所以这个窗口就变为不可变动大小的了,也可以只使用一个setFixedSize()方法来设定:QWidget *parent = new QWidget;parent-setWindowTitle(Signal & Slot);parent-setMinimumSize(240, 140);parent-setMaximumSize(240, 140);这个QWidget没有指定parent,所以它是一个独立窗口,接下来的QLCDNumber实例建立时,指定了这个QWidget为它的parent,所以QLCDNumber被置入了QWidget之中成为child,可显示的范围限制在p

15、arent的边界大小之中,它在parent中的位置为X: 70、Y: 20,长为100、宽为30(setGeometry()):QLCDNumber *lcd = new QLCDNumber(parent);lcd-setGeometry(70, 20, 100, 30);接下来的QSlider实例在建立时,也指定了这个QWidget为它的parent,程序中设定QSlider为水平拉杆(Qt: Horizontal),可拉动的数值范围为0到99(setRange()),目前拉杆光标值为0(setValue()),而它在parent中的位置为X: 70、Y: 70,长为100、宽为30:QS

16、lider *slider = new QSlider(Qt:Horizontal,parent);slider-setRange(0, 99);slider-setValue(0);slider-setGeometry(70, 70, 100, 30); 当您拉动QSlider的光标,造成光标值变动时会发出valueChanged(int) Signal,参数int表示Signal带有一个整数值,在这表示QSlider的游标值一并被发出,QLCDNumber的display(int) Slot接受Signal所带来的整数值,可以在QLCDNumber显示数字:QObject:connect(

17、slider, SIGNAL(valueChanged(int),lcd, SLOT(display(int);一个程序执行时的参考画面如下所示:注意:1. Signal与Slot的签名基本上要相同,但若Signal的参数多于Slot的参数,则额外的参数会被Slot忽略。2. 一个Signal可以关联多个Slot函数。3. Signal也可以和Signal关联。(消息消息)4. Qt管理的对象必须继承QObject类别,以提供Qt对象的Meta讯息,若要实作Signal与Slot机制,则必须包括Q_OBJECT宏,moc会处理Qt的C+扩充(Meta-Object System),使用moc读

18、取C+标头档案,若发现类别定义中包括Q_OBJECT宏,就会产生Qt meta-object相关的C+程序代码。5. QT Creator开发QT程序时候,请确保信号和槽函数书写正确。在编译时,编译器不会对信号和槽函数中的书写错误做出判断)。 例如: connect(OBJECT1, SIGNAL(signalName(bool), OBJECT2, SLOT(slotName(bool);2.4事件处理机制1) 事件类型及处理者执行QApplication的exec()方法之后,应用程序会进入事件循环来倾听应用程序的事件,事件来源通常是窗口系统,例如使用者的鼠标事件或键盘事件,事件来源可以是

19、Qt应用程序事件本身,例如QTimerEvent(定时器),事件来源也可以是使用者自定义的事件,通过QApplicaiton的sendEvent()或postEvent()来发送。 当事件发生时,Qt为之建立事件实例,QEvent是Qt中所有事件的基类,Qt所建立的事件实例为QEvent的子类别实例,并将之传送给 QObject子类实例的event()函式,event()这个函式本身通常不直接处理事件,而是基于所传送的事件类型,分派给处理特定类型的事件处理者(Event Handler)。QEvent是Qt中所有事件的基础类别,最常见的事件类型皆为其子类别,像是鼠标事件的QMouseEvent

20、、键盘事件的QKeyEvent、缩放事件的QResizeEvent等,这些子类别事件皆加入其特定的函数,像是鼠标事件的x()、y()函数指出发生鼠标事件时,鼠标光标的x、y坐标,键盘事件的key()函数可以取得目前所按下的按键常数。以图型组件来说,通常我们会继承QWidget或其子类,并重新定义事件的处理函数,QWidget定义了像是 keyPressEvent()、keyReleaseEvent()、mouseDoubleClickEvent()、mouseMoveEvent ()、mousePressEvent()、mouseReleaseEvent()等事件处理函数,并接受QEvent的

21、特定子类别实例作为自变量,只要根据想要处理的事件重新定义对应的函式即可进行事件处理。以下则是个简单的事件处理示范,继承了QLabel并重新定义了相关的事件处理者,当鼠标移动、按下或放开时,显示鼠标光标的所在位置:#include #include #include #include class EventLabel : public QLabel protected: void mouseMoveEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEv

22、ent *event);void EventLabel:mouseMoveEvent(QMouseEvent *event) QString msg; msg.sprintf(Move: (%d, %d), event-x(), event-y(); this-setText(msg);void EventLabel:mousePressEvent(QMouseEvent *event) QString msg; msg.sprintf(Press: (%d, %d), event-x(), event-y(); this-setText(msg);void EventLabel:mouseR

23、eleaseEvent(QMouseEvent *event) QString msg; msg.sprintf(Release: (%d, %d), event-x(), event-y(); this-setText(msg);int main(int argc, char *argv) QApplication app(argc, argv); EventLabel *label = new EventLabel; label-setWindowTitle(MouseEvent Demo); label-resize(300, 200); label-show(); return app

24、.exec();执行时的参考画面如下所示:注意:Qt的事件跟Signal、Slot机制是不同的。Signal与Slot的机制是同步的(Synchronous),Signal是由对象发出的,使用QObject的connect()连接对象上定义的Slot来立即处理。Qt的事件可以是异步的(Asynchronous)的,QT使用一个事件队列来维护,新的事件产生时基本上会被排到队列的尾端,前一个事件处理完成,再从队列的前端取出下一个队列来处理,必要的时候,Qt的事件也可以是同步的,而事件还可以使用事件过滤器进行过滤处理。2) 事件类型及处理者不同类型的事件,都有对应的事件处理函数,它们接受QEvent

25、的特定子类别实例作为自变量,像是下例中mousePressEvent()事件处理函数上的 QMouseEvent,您可以针对事件的某些状况作特定处理,而其它未处理的状况,则呼叫父类别对应的的事件处理函式,让父类别预先定义的事件处理可以完成: void CustomLabel:mousePressEvent(QMouseEvent *event) if (event-button() = Qt:LeftButton) / 处理左键按下 / . else / 由父类别所定义的事件处理函式来事件 QLabel:mousePressEvent(event); void CustomLabel:mous

26、eReleaseEvent(QMouseEvent *event) / 鼠标放开事件处理.事实上,每个可传递的事件都有accept()与igore()两个方法,用以告知Qt应用程序,这个事件处理者是否接受或忽略此一事件,如果事件处理者中呼叫事件的accept(),则事件不会再进一步传播,若呼叫了ignore(),则Qt应用程序会尝试寻找另一个事件的接受者,您可以藉由isAccepted()方法得知事件是否被接受。一般来说,除了QCloseEvent之外,很少直接呼叫accept()或ignore(),如果您接受事件,则在事件处理者当中实作对事件的处理(如上例的if陈述句),如果您不接受事件,则

27、直接呼叫父类别的事件实作(如上例的else陈述句),对于QWidget来说,预设的实作是:void QWidget:keyPressEvent(QKeyEvent *event) event-ignore();由于QWidget预设的实作是呼叫ignore(),这让事件可以向父组件传播。 QCloseEvent则建议直接呼叫accept()与ignore(),accept()方法会继续关闭的操作,ignore()则会取消关闭的操作:void MainWindow:closeEvent(QCloseEvent *event) if (continueToClose() event-accept(

28、); else event-ignore(); QObject的event()方法通常用于分派事件,但在某些情况下,您希望在事件分派给其它事件处理者之前,先行作一些处理,则可以重新定义event()方法,例如在窗口程序中,Tab键按下时希望其将焦点移至下一个图型组件,而不是直接让目前焦点的图形组件直接处理Tab键,则您可以在继承QWidget子类别时,重新定义其event()方法,例如:bool CustomWidget:event(QEvent *event) if (event-type() = QEvent:KeyPress) QKeyEvent *keyEvent = static_c

29、ast(event);if (keyEvent-key() = Qt:Key_Tab) / 处理Tab键return true;return QWidget:event(event); 在执行时期想要知道所取得之QEvent类型,可以使用QEvent的type()方法取得常数值,并与QEvent:Type作比对。3) 事件过滤器Qt将事件封装为QEvent实例之后,会呼叫QObject的event()方法并将QEvent实例传送给它,在某些情况下,您希望对象在执行event()处理事件之前,先对一些事件进行处理或过滤,然后再决定是否呼叫event()方法,这个时候您就可以使用事件过滤器。 上面

30、提到的对QWidget按键事件的Tab键处理而言,如果您的图形接口中有很多的组件,每个图型组件都要如当中的范例重新定义event()方法,显然是非常没有效率且没什么维护性的方法。 您可以自定义一个对象继承QObject(或其子类别),重新定义它的eventFilter()方法,例如您自定义了一个FilterObject,您希望Tab键可以用来将焦点转移至下一个子组件:bool FilterObject:eventFilter(QObject *object, QEvent *event) if(event-type() = QEvent:KeyPress) QKeyEvent *keyEven

31、t = static_cast(event);if (keyEvent-key() = Qt:Key_Tab) / 处理Tab键 return true; return false; eventFilter()的object参数表示事件发生的来源对象,eventFilter()若传回false,则安装该事件过滤器的对象之event()就会继续执行,若传回true,则安装该事件过滤器的对象之event()方法就不会被执行,由此进行事件的拦截处理。要为指定的对象安装事件过滤器,可以使用对象的installEventFilter()方法,例如:QLineEdit *nameEdit = new QL

32、ineEdit;QLineEdit *addressEdit = new QLineEdit;.FilterObject filter = new FilterObject;.nameEdit-installEventFilter(filter);addressEdit-installEventFilter(filter);.您也可以将事件过滤器安装在QApplication,在任何的事件发生后呼叫每个对象的event()方法之前,会先经过事件过滤器,这给您更多控制应用程序事件的能力。 Qt的事件循环与sendEvent()方法会呼叫QCoreApplication(QApplication的

33、父类别)的notify()以分派事件,如果您想要完全控制Qt应用程序的事件,则可以重新定义notify()方法。 可以看出Qt事件处理的五个层次:重新定义事件处理者、重新定义event()方法、为个别对象安装事件过滤器、为QApplication安装事件过滤器,重新定义QCoreApplication的notify()方法。2.4 布局管理器设计窗口程序的人都知道,在窗口程序中最麻烦也最难的就是版面配置,每次都为了组件的位置摆放在伤脑筋,当然我们可以通过 setGeometry()来设定Widget于parent中的XY位置与长宽,但这样在您窗口缩放时,当中的组件位置并不会适当的自我调整大小、

34、位置(或像是字号自动调整之类的),以配合窗口缩放展现适当的观感。所以窗口程序的解决方案都会提供一些现成的版面配置方式,让您可以不必自行配置组件位置,以下直接看例子,使用QHBoxLayout进行组件的版面配置,这可以让您以水平的方式来摆放组件:#include #include #include #include #include int main(int argc, char *argv) QApplication app(argc, argv); QWidget *window = new QWidget; window-setWindowTitle(QHBoxLayout); windo

35、w-resize(250, 50); QLCDNumber *lcd = new QLCDNumber; QSpinBox *spinBox = new QSpinBox; spinBox-setRange(0, 99) ; QObject:connect(spinBox, SIGNAL(valueChanged(int), lcd, SLOT(display(int); QHBoxLayout *layout = new QHBoxLayout; layout-addWidget(spinBox); layout-addWidget(lcd); window-setLayout(layout

36、); window-show(); return app.exec();这个程序中,没有自行设定组件的parent/child关系,也没有设定组件的大小、位置,而直接使用QHBoxLayout将组件加入,这会把 QHBoxLayout及其管理的组件设成程序中window的子组件,并依QHBoxLayout版面配置策略自动水平配置组件,一个执行的的画面如下所示组件会自动填满窗口,如果您拉动窗口,则当中的组件也会适当的变动大小:QHBoxLayout中组件的加入顺序,就是水平配置由左至右显示的顺序,至于QVBoxLayout的使用方式则与QHBoxLayout类似,再来一个例子改用QVBoxLay

37、out来配置组件位置:#include #include #include #include #include int main(int argc, char *argv) QApplication app(argc, argv); QWidget *window = new QWidget; window-setWindowTitle(QVBoxLayout); window-resize(240, 100); QLCDNumber *lcd = new QLCDNumber; QSlider *slider = new QSlider(Qt:Horizontal); slider-setR

38、ange(0, 99); slider-setValue(0); QObject:connect(slider, SIGNAL(valueChanged(int), lcd, SLOT(display(int); QVBoxLayout *layout = new QVBoxLayout(window); layout-addWidget(lcd); layout-addWidget(slider); window-show(); return app.exec();程序中可以看到,在建立版面配置对象时,也可以直接指定要实施版面配置的对象。拉动时的画面如下所示:2.5 绘图QPainter、Q

39、PaintEngine、QPaintDevice组成了Qt的绘图系统,QPainter 提供低阶的绘图API,在内部使用QPaintEngine作为接口,在QPaintDevice进行绘图,只要是QPaintDevice的子类别,就可以建立QPainter在其上进行图形绘制,像是QWidget、QImage、QPicture、QPrinter等都是QPaintDevice的子类别。 建立QPainter的方式如下,其中qPainterDevice是个指向QPaintDevice子类别的名称:QPainter painter(qPainterDevice);若是图形组件,通常会重新定义QWidg

40、et的paintEvent(),当绘图装置(Paint Device)需要重绘时,就会发出QPaintEvent并分派给这个方法来处理事件,例如组件出现、被覆盖又重现时,您也可以呼叫repaint() 或update(),这也会执行paintEvent()。QPainter提供各种绘制图形的API,从基本的线绘制、方块、矩形、圆形、渐层到复杂的图片等,QPainter都有提供相对应的API,使用的方式参考QT帮助文档。在这边基本上要先了解的是,QPainter的三个基本设定:笔触(Pen)、笔刷(Brush)与字型(Font)。笔触在Qt中是以QPen作代表,用来于绘制线条或轮廓时决定样式,像

41、是颜色、笔宽、转折、线条样式(实线、曲线、点状线之类的样式)等。笔刷在Qt中是以QBrush作代表,用来于绘制矩形、圆形、扇形等几何图形时决定样式,像是颜色、填满样式、渐层等。以下先看一个简单的程序,了解一下QPainter的几个API,以及QPen、QBrush的使用:#include #include #include class PainterWidget : public QWidget protected: / 重新定义paintEvent()事件处理 void paintEvent(QPaintEvent*);/ 实作事件处理void PainterWidget:paintEven

42、t(QPaintEvent *event) / 建立QPainter QPainter painter(this); / 设定笔触为点状线 painter.setPen(Qt:DotLine); / 指定x、y、width、height绘制线条 painter.drawLine(10, 10, 100, 10); / 设定笔刷为蓝色、对角斜线样式 painter.setBrush(QBrush(Qt:blue, Qt:BDiagPattern); / 指定x、y、width、height绘制矩形 painter.drawRect(10, 20, 100, 50); / 设定线形渐层,x1,y1

43、为起点,x2,y2为终点 QLinearGradient gradient(50, 100, 300, 350); / 设定渐层颜色过渡 gradient.setColorAt(0.0, Qt:white); gradient.setColorAt(0.2, Qt:green); gradient.setColorAt(1.0, Qt:black); / 以渐层对象建立笔刷 painter.setBrush(QBrush(gradient); / 绘制圆角矩形 painter.drawRoundRect(10, 80, 100, 50); / 绘制扇形,单位为 1/16 角度,下例为 45 度

44、 到 300 度 painter.drawPie(10, 150, 100, 50, 45 * 16, 300 * 16); / 绘制图片 painter.drawPixmap(150, 10, QPixmap(caterpillar.jpg); / 绘制填满图形 painter.drawTiledPixmap(150, 170, 185, 25, QPixmap(caterpillar_smaill.gif);int main(int argc, char *argv) QApplication app(argc, argv); PainterWidget pWidget; pWidget.

45、setWindowTitle(QPainter); pWidget.resize(350, 200); pWidget.show(); return app.exec();执行的结果如下所示:2.6 网络QHttp是Qt所提供有关网络的高阶API,可以协助您进行HTTP协议的进行,QHttp发出请求时是异步的,请求的过程中会发出相关的Signal,您可以用Slot来接收这些Signal,并进行相关的处理。以下先示范一个最基本的QHttp使用,程序将设计一个HttpGet类别: HttpGet.h #ifndef HTTPGET_H#define HTTPGET_H#include class

46、QUrl;class QHttp;class QFile;class HttpGet : public QObject Q_OBJECTpublic: HttpGet(QObject *parent = 0); void downloadFile(const QUrl &url); signals: void finished(); private slots: void done(bool error); private: QHttp *http; QFile *file;#endif这个HttpGet可以让您指定档案的URL地址,以HTTP方式取得档案并储存在本地端,URL在Qt中以QUr

47、l代表,当档案下载完成时,会发出finished()的Signal,当QHttp所排定的全部请求完成时,会发出done()的Signal,HttpGet类别中自定的Slot,就是用来接收QHttp的done() Signal以进行相关处理,这可以在HttpGet的实作看到: HttpGet.cpp #include #include #include #include HttpGet.husing namespace std;HttpGet:HttpGet(QObject *parent) : QObject(parent) http = new QHttp(this); connect(ht

48、tp, SIGNAL(done(bool), this, SLOT(done(bool);void HttpGet:downloadFile(const QUrl &url) QFileInfo fileInfo(url.path(); QString fileName = fileInfo.fileName(); if (fileName.isEmpty() fileName = index.html; file = new QFile(fileName); if (!file-open(QIODevice:WriteOnly) cerr Unable to save the file se

49、tHost(url.host(), url.port(80); http-get(url.path(), file); http-close();void HttpGet:done(bool error) if (error) cerr Error: errorString() endl; else cerr File downloaded as fileName() close(); delete file; file = 0; emit finished();要使用Qt的网络相关类别,必须引进QtNetwork,并且必须在.pro档案中,加入以下这行以在建构过程中使用Qt网络模块:QT +

50、= network当呼叫HttpGet类别的downloadFile()方法时,程序中使用QUrl的path()来取得路径讯息,如果路径讯息中没有包括文件名,就使用预设的index.html作为请求的对象及下载后存盘时的档名,要使用QHttp来请求档案时,必须使用setHost ()来设定主机及连接端口信息,接着使用get()方法发出请求,并告知下载的档案要到用哪个QFile来存盘。 当QHttp所有请求处理完毕后,会发出done()的Signal,程序中将之连接至HttpGet的done()来处理,处理完成之后,再发出finished()的Signal。以下写个简单的程序来测试HttpGet

51、: main.cpp #include #include #include HttpGet.h#include using namespace std;int main(int argc, char *argv) QCoreApplication app(argc, argv); HttpGet getter; getter.downloadFile(QUrl( QObject:connect(&getter, SIGNAL(finished(), &app, SLOT(quit(); return app.exec();程序中将HttpGet的finished()的Signal连接至QCor

52、eApplication的quit(),如此当下载档案完成后,可以直接关闭应用程序。Qt的QHttp与QFtp在使用上有许多类似的地方,可以在以上的范例看到一些特性,以下再整理出相关特性: 非阻断行为,请求是异步的。 您可以排定一连串的请求,每个请求都有一个Command ID,QHttp的requestStarted()与requestFinished()等Signal会带有请求的Command ID,您可以用以追踪请求的执行。 在数据传输的过程中,有相关的Signal可以追踪进度,像是QHttp的dataReadProgress()、dataSendProgress()等Signal。 支

53、持QIODevice的写入(下载)与读取(上传),还有以QByteArray为基础的API。QHttp还可以针对请求标头、HTTPS等加以处理,在Qt的在线文件中,有个QHttp的范例 Http Example,对QHttp的使用有更完整的示范。2.7 多线程1) Qthread在Qt中要实现线程功能,可以继承QThread类别,并重新定义run()方法,之后要启动一个线程,则建构这个自订的对象,并执行start()方法。下面这个程序是个简单的程序,您可以看到如何继承QThread、重新定义run()方法及如何启动线程,程序中将以两个线程同时对一个QPixmap画圆,显示两个同时进行的流程:

54、CircieThread.h #ifndef CIRCLETHREAD_H#define CIRCLETHREAD_H#include class QLabel;class QPixmap;class CircleThread : public QThread Q_OBJECTpublic: CircleThread(QLabel *label, QPixmap *pixmap, int y); protected: void run();private: QLabel *label; QPixmap *pixmap; int y;#endifCircleThread建构函式中,QPixmap

55、是QLabel将显示的图片,而y值是画圆时的位置,CircleThread实作如下: CircleThread.cpp #include CircleThread.h#include #include #include CircleThread:CircleThread(QLabel *label, QPixmap *pixmap, int y) this-label = label; this-pixmap = pixmap; this-y = y;void CircleThread:run() QPainter painter(pixmap); for(int i = 10; i setPixmap(*pixmap); QThread:mslee

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!