lect01-Qt信號(hào)槽_第1頁(yè)
lect01-Qt信號(hào)槽_第2頁(yè)
lect01-Qt信號(hào)槽_第3頁(yè)
lect01-Qt信號(hào)槽_第4頁(yè)
lect01-Qt信號(hào)槽_第5頁(yè)
已閱讀5頁(yè),還剩93頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、1,HelloWorld,2,HELLO QT (1),#include #include int main(int argc, char *argv) QApplication app(argc, argv); QLabel *label = new QLabel(Hello Qt!); label-show(); return app.exec(); ,3,HELLO QT (2): 用HTML格式化,#include int main(int argc, char *argv) QApplication app(argc, argv); QLabel *label = new QLabe

2、l(Hello Qt!); label-show(); return app.exec(); ,4,Qt編譯過(guò)程,5,Qt編譯過(guò)程,方法一:直接通過(guò)Qt IDE(Qt Creator)界面直接編譯 方法二:命令行編譯 執(zhí)行“qmake -project” 創(chuàng)建 Qt 工程文件(.pro),該工程文件也可以手動(dòng)創(chuàng)建 執(zhí)行“qmake” 缺省輸入為工程文件,產(chǎn)生平臺(tái)相關(guān)的 Makefile(s) 產(chǎn)生編譯規(guī)則,為工程中包含有 Q_OBJECT 宏的頭文件調(diào)用 moc 編譯器 執(zhí)行“make” 編譯程序 執(zhí)行moc, uic和rcc,6,Qt編譯工具:moc, uic 和 rcc,moc, 元對(duì)象(

3、Meta-Object Compiler)編譯器 對(duì)每一個(gè)類(lèi)的頭文件,產(chǎn)生一個(gè)特殊的 meta-object Meta-object 由 Qt 使用 uic, Ui編譯器 根據(jù)Qt Designer產(chǎn)生的XML文件(.ui)生成對(duì)應(yīng)的頭文件代碼 rcc, 資源編譯器 生成包含Qt資源文件(.qrc)中數(shù)據(jù)(如工具欄圖標(biāo)等)的C+源文件 這些工具在編譯的時(shí)候由Makefile管理,自動(dòng)運(yùn)行,7,Qt應(yīng)用程序執(zhí)行過(guò)程,8,Qt應(yīng)用程序執(zhí)行過(guò)程事件驅(qū)動(dòng),9,Qt事件處理,在X程序中,敲擊鍵盤(pán),鼠標(biāo)指針在窗口中的移動(dòng)或鼠標(biāo)按鍵動(dòng)作等,都是事件 Qt事件的處理過(guò)程 QApplication的事件循環(huán)體從

4、事件隊(duì)列中拾取本地窗口系統(tǒng)事件或其他事件 譯成QEvent,并送給QObject:event(),最后送給QWidget:event()分別對(duì)事件處理,10,Qt事件處理(續(xù)),11,Qt程序要素和主要基類(lèi),12,主要基類(lèi):QObject類(lèi),Qt對(duì)象模型的核心 QObject類(lèi) QObject在整個(gè)Qt的體系中處于一個(gè)非常重要的位置 是幾乎所有Qt類(lèi)和所有部件(widget)的基類(lèi) 所有的QWidgets都是QObject 提供對(duì)象樹(shù)和對(duì)象的關(guān)系 提供了信號(hào)-槽的通信機(jī)制 對(duì)象不允許拷貝(禁用拷貝構(gòu)造函數(shù)) 包含了很多組成Qt的機(jī)制 事件處理 屬性,內(nèi)?。↖ntrospection) 內(nèi)存管理

5、,13,QApplication類(lèi),QApplication類(lèi)負(fù)責(zé)GUI應(yīng)用程序的控制流和主要的設(shè)置,包括: 主事件循環(huán)體,負(fù)責(zé)處理和調(diào)度所有來(lái)自窗口系統(tǒng)和其他資源的事件 處理應(yīng)用程序的開(kāi)始、結(jié)束以及會(huì)話(huà)管理 還包括系統(tǒng)和應(yīng)用程序方面的設(shè)置 在Qt應(yīng)用程序中,首先要?jiǎng)?chuàng)建一個(gè)QApplication對(duì)象 不管有多少個(gè)窗口,QApplication對(duì)象只能有一個(gè),而且必須在其他對(duì)象之前創(chuàng)建 可以利用全局指針qApp訪(fǎng)問(wèn)QApplication對(duì)象 QApplication是QObject的子類(lèi),14,QApplication類(lèi),QApplication類(lèi)中封裝很多函數(shù),其中包括: 系統(tǒng)設(shè)置:set

6、Font() 用來(lái)設(shè)置字體 事件處理:sendEvent() 用來(lái)發(fā)送事件 GUI風(fēng)格:setStyles() 設(shè)置圖形用戶(hù)界面的風(fēng)格 顏色使用:colorSpec() 用來(lái)返回顏色文件 文本處理:translate() 用來(lái)處理文本信息 創(chuàng)建組件:setmainWidget() 用來(lái)設(shè)置窗口的主組件 ,15,16,程序退出,退出事件程序,只需要在程序結(jié)束時(shí)返回一個(gè)exec(),例如: return app.exec(); 其中app為QApplication的實(shí)例,當(dāng)調(diào)用exec()將進(jìn)入主事件的循環(huán)中,直到exit()被調(diào)用或主窗口部件被銷(xiāo)毀,#include #include int m

7、ain(int argc, char *argv) QApplication app(argc, argv); QLabel *label = new QLabel(Hello Qt!); label-show(); return app.exec(); ,17,QApplication類(lèi)負(fù)責(zé)程序退出,退出應(yīng)用程序可以調(diào)用繼承自QCoreApplication類(lèi)的quit或exit函數(shù) QApplication是QCoreApplication類(lèi)的子類(lèi) quit ():告訴應(yīng)用程序退出,并返回0(表示成功) exit(0):同quit() 舉例 QPushButton *quitButton

8、= new QPushButton(Quit); connect(quitButton, SIGNAL(clicked(), qApp, SLOT(quit(); 或 qApp-exit(0);,18,QApplication類(lèi)負(fù)責(zé)關(guān)閉窗口,調(diào)用QApplication:closeAllWindows () 尤其適用于有多個(gè)頂層窗口的應(yīng)用程序 如果關(guān)閉窗口后,不想讓?xiě)?yīng)用程序退出,則需要調(diào)用函數(shù) QApplication:setQuitOnLastWindowClosed (false) 舉例 exitAct = new QAction(tr(E,19,QWidget類(lèi)負(fù)責(zé)窗口部件,QWidge

9、t類(lèi)是所有用戶(hù)界面對(duì)象的基類(lèi),是QObject類(lèi)的子類(lèi),繼承了QObject類(lèi)的屬性。 窗口部件是用戶(hù)界面的一個(gè)原子:它從窗口系統(tǒng)接收鼠標(biāo)、鍵盤(pán)和其它事件,并且在屏幕上繪制自己的表現(xiàn)。 按鈕(Button)、菜單(menu)、滾動(dòng)條(scroll bars)和框架(frame)都是窗口部件的例子。 通常,應(yīng)用程序都是一個(gè)控件,只是這個(gè)控件是由很多其它的控件組成,20,QWidget類(lèi)(續(xù)),窗口部件可以包含其它的窗口部件。例如,一個(gè)應(yīng)用程序界面通常就是一個(gè)包含了QMenuBar,一些QToolBar,一個(gè)QStatusBar和其它的一些部件的窗口。 絕大多數(shù)應(yīng)用程序使用一個(gè)QMainWindo

10、w或者一個(gè)QDialog作為程序界面,但是Qt允許任何窗口部件成為窗口。 當(dāng)窗口部件被創(chuàng)建的時(shí)候,它總是隱藏的,必須調(diào)用show()來(lái)使它可見(jiàn)。 QWidget類(lèi)有很多成員函數(shù),但一般不直接使用,而是通過(guò)子類(lèi)繼承來(lái)使用其函數(shù)功能。如,QPushButton、QlistBox等都是它的子類(lèi),21,22,QMainWindow類(lèi)負(fù)責(zé)窗口創(chuàng)建,在Qt程序中,創(chuàng)建窗口比較簡(jiǎn)單,只要在main.cpp文件中為ApplicationWindow建立一個(gè)指針: ApplicationWindow *mw = new ApplicatonWindow(); ApplicationWindow是在Applica

11、tion.h中定義的類(lèi),它是一個(gè)QMainWindow的子類(lèi) QMainWindow類(lèi)是QWidget的子類(lèi),用于創(chuàng)建帶有菜單欄和工具欄的窗口,如windows系統(tǒng)的瀏覽器 另外,有QDialog類(lèi)也是QWidget的子類(lèi),與QMainWindow不同的是,QDialog類(lèi)用于創(chuàng)建對(duì)話(huà)框窗口,如多數(shù)軟件都有的“關(guān)于”對(duì)話(huà)框。,23,Qt屬性與內(nèi)省,24,元數(shù)據(jù)(Meta data),Qt用C+實(shí)現(xiàn)內(nèi)?。↖ntrospection) 每一個(gè) QObject 都有一個(gè)元對(duì)象 元對(duì)象涉及: 類(lèi)名 (QObject:className) 繼承 (QObject:inherits) 屬性 信號(hào)和槽 普通

12、信息(QObject:classInfo),25,元數(shù)據(jù),元數(shù)據(jù)通過(guò)元對(duì)象編譯器(moc)在編譯時(shí)組合在一起。,sources *.cpp,executables,object files *.o,headers *.h,普通的C+生成過(guò)程,includes,compiles,links,26,元數(shù)據(jù)Meta data,元數(shù)據(jù)通過(guò)元對(duì)象編譯器(moc)在編譯時(shí)組合在一起。 moc從頭文件里面獲得數(shù)據(jù)。,sources *.cpp,executables,object files *.o,headers *.h,generated moc_*.cpp,Qt C+ 生成過(guò)程,includes,co

13、mpiles,links,compiles,mocs,27,元數(shù)據(jù),moc 找什么?,class MyClass : public QObject Q_OBJECT Q_CLASSINFO(author, John Doe) public: MyClass(const Foo ,28,內(nèi)省(Introspection),類(lèi)在運(yùn)行時(shí)了解它們自己的信息 對(duì)實(shí)現(xiàn)腳本和動(dòng)態(tài)語(yǔ)言的綁定有很好的支持。,if (object-inherits(QAbstractItemView) QAbstractItemView *view = static_cast(widget); view-. enum Capit

14、alsEnum Oslo, Helsinki, Stockholm, Copenhagen ; int index = object-metaObject()-indexOfEnumerator(CapitalsEnum); object-metaObject()-enumerator(index)-key(object-capital();,29,屬性(Properties),QObject有g(shù)etter和setter函數(shù)屬性 命名策略: color, setColor 對(duì)于布爾類(lèi)型: isEnabled, setEnabled,class QLabel : public QFrame Q_

15、OBJECT Q_PROPERTY(QString text READ text WRITE setText) public: QString text() const; public slots: void setText(const QString ,30,屬性,為什么使用setter 函數(shù)? 可以驗(yàn)證設(shè)置 對(duì)可能的變化作出反應(yīng),void setMin( int newMin ) if( newMin m_max ) qWarning(Ignoring setMin(%d) as min max., newMin); return; .,void setMin( int newMin )

16、. m_min = newMin; updateMinimum(); ,31,屬性,為什么使用getter 函數(shù)? 間接的屬性,QSize size() const return m_size; int width() const return m_size.width(); ,32,屬性,Q_PROPERTY(type name READ getFunction WRITE setFunction RESET resetFunction NOTIFY notifySignal DESIGNABLE bool SCRIPTABLE bool STORED bool USER bool CONS

17、TANT FINAL),屬性跟類(lèi)中數(shù)據(jù)成員的主要區(qū)別 必須有一個(gè)read函數(shù) 有一個(gè)可選的write函數(shù) 如果定義了stored屬性表明這是一直存在的。 一個(gè)reset函數(shù)能夠把property設(shè)置成其默認(rèn)狀態(tài) 一個(gè)designable屬性表明該property能在GUI builder(一般為Qt Designer)可見(jiàn) 注意: Q_PROPERTY 主要用于Qt Designer plugin (插件)開(kāi)發(fā)中,33,使用屬性,直接獲取 通過(guò)元信息和屬性系統(tǒng) 在運(yùn)行時(shí)發(fā)現(xiàn)屬性,QString text = label-text(); label-setText(Hello World!);,

18、QString text = object-property(text).toString(); object-setProperty(text, Hello World);,int QMetaObject:propertyCount(); QMetaProperty QMetaObject:property(i); QMetaProperty:name/isConstant/isDesignable/read/write/.,34,動(dòng)態(tài)屬性,在運(yùn)行時(shí)給對(duì)象增加屬性 可以用來(lái)“標(biāo)識(shí)”對(duì)象,等等。,bool ret = object-setProperty(name, value);,QObje

19、ct:dynamicPropertyNames() const,35,創(chuàng)建自定義屬性,class AngleObject : public QObject Q_OBJECT Q_PROPERTY(qreal angle READ angle WRITE setAngle) public: AngleObject(qreal angle, QObject *parent = 0); qreal angle() const; void setAngle(qreal); private: qreal m_angle; ;,36,創(chuàng)建自定義屬性,AngleObject:AngleObject(qrea

20、l angle, QObject *parent) : QObject(parent), m_angle(angle) qreal AngleObject:angle() const return m_angle; void AngleObject:setAngle(qreal angle) m_angle = angle; doSomething(); ,37,自定義屬性 - 枚舉,class AngleObject : public QObject Q_OBJECT Q_ENUMS(AngleMode) Q_PROPERTY(AngleMode angleMode READ .) publ

21、ic: enum AngleMode Radians, Degrees; . ;,38,Qt對(duì)象樹(shù)及內(nèi)存管理,39,QObject類(lèi)(續(xù))-父子關(guān)系,每一個(gè)QObject對(duì)象都可以有一個(gè)指向父親的參數(shù) 孩子會(huì)通知他的父親自己的存在,父親會(huì)把它加入到自己的孩子列表中 如果一個(gè)widget對(duì)象沒(méi)有父親,那么他就是一個(gè)窗口 父部件可以: 當(dāng)父部件隱藏或顯示自己的時(shí)候,會(huì)自動(dòng)的隱藏和顯示子部件 當(dāng)父部件enable和disable時(shí),子部件的狀態(tài)也隨之變化 注意:在父部件可見(jiàn)的時(shí)候,子部件也可以單獨(dú)隱藏自己,40,改變所有者,QObject可以修改它所屬的父對(duì)象。 父對(duì)象知道何時(shí)子對(duì)象被刪除 一系列函

22、數(shù)實(shí)現(xiàn)返回指針,從其所有者“拿走”釋放的數(shù)據(jù),把它留給拿取者處理,obj-setParent(newParent);,delete listWidget-item(0); / 刪除第一個(gè)item(不安全),QLayoutItem *QLayout:takeAt(int); QListWidgetItem *QListWidget:takeItem(int); / Safe alternative QListWidgetItem *item = listWidget-takeItem(0); if (item) delete item; ,41,QObject類(lèi)(續(xù))-內(nèi)存管理,所有子對(duì)象的內(nèi)存

23、管理都轉(zhuǎn)移給了父對(duì)象 使用new在堆上分配內(nèi)存 子對(duì)象可自動(dòng)被父對(duì)象刪除內(nèi)存 手動(dòng)刪除不會(huì)引起二次刪除,因?yàn)樽訉?duì)象刪除時(shí)會(huì)通知父對(duì)象 沒(méi)有父對(duì)象的QObject對(duì)象都需要手動(dòng)刪除 一般把這種無(wú)父親的對(duì)象分配在棧上,可以避免內(nèi)存泄露的問(wèn)題 Qt是否有類(lèi)似于自動(dòng)回收站的機(jī)制?但是事實(shí)是沒(méi)有的! 只需要關(guān)注對(duì)象的父子關(guān)系和功能!,42,內(nèi)存管理,QObject 可以有父對(duì)象和子對(duì)象 當(dāng)一個(gè)父對(duì)象被刪除,它的子對(duì)象也同樣被刪除。,QObject *parent = new QObject(); QObject *child1 = new QObject(parent); QObject *child2

24、 = new QObject(parent); QObject *child1_1 = new QObject(child1); QObject *child1_2 = new QObject(child1); delete parent;,parent,child1,child2,child1_1,child1_2,43,內(nèi)存管理,當(dāng)需要實(shí)現(xiàn)視覺(jué)層級(jí)時(shí)使用到它,QDialog *parent = new QDialog(); QGroupBox *box = new QGroupBox(parent); QPushButton *button = new QPushButton(parent

25、); QRadioButton *option1 = new QRadioButton(box); QRadioButton *option2 = new QRadioButton(box); delete parent;,44,使用模式,使用 this指針指向最高層父對(duì)象 在棧上分配父對(duì)象空間,void Widget:showDialog() Dialog dialog; if (dialog.exec() = QDialog:Accepted) . ,Dialog:Dialog(QWidget *parent) : QDialog(parent) QGroupBox *box = QGro

26、upBox(this); QPushButton *button = QPushButton(this); QRadioButton *option1 = QRadioButton(box); QRadioButton *option2 = QRadioButton(box); .,45,構(gòu)造規(guī)范,幾乎所有的 QObject 都有一個(gè)默認(rèn)為空值的父對(duì)象。 QWidget 的父對(duì)象是其它 QWidget類(lèi) 為了方便傾向于提供多種構(gòu)造(包括只帶有父對(duì)象的一種) 父對(duì)象通常是帶缺省值的第一個(gè)參數(shù)。,QLabel(const QString ,QObject(QObject *parent=0);,Q

27、PushButton(QWidget *parent=0); QPushButton(const QString ,46,構(gòu)造規(guī)范,當(dāng)創(chuàng)建自己的 QObject時(shí), 需考慮 總是允許父對(duì)象 parent 為 0 (null) 有一個(gè)只接受父對(duì)象的構(gòu)造函數(shù) parent 是帶默認(rèn)值的第一個(gè)參數(shù) 提供幾種構(gòu)造函數(shù),避免空值、無(wú)效值(e.g. QString()作為參數(shù)。,47,QObject類(lèi)對(duì)象,QObject類(lèi)是所有能夠處理signal、slot和事件的Qt對(duì)象的基類(lèi),原形如下: QObject:QObject ( QObject*parent =0,constchar*name = 0 )

28、創(chuàng)建帶有父對(duì)象及其名字的對(duì)象,對(duì)象的父對(duì)象可以看作這個(gè)對(duì)象的所有者。比如,對(duì)話(huà)框是其中的ok和cancel按鈕的父對(duì)象。 在上面的函數(shù)中如果parent為0則構(gòu)造一個(gè)無(wú)父的對(duì)象,如果對(duì)象是一個(gè)組件,則它就會(huì)成為頂層的窗口。,48,QObject類(lèi)(實(shí)例),class Mandelbrot:public QObject Q_OBJECT /需要使用signal和slot public: Mandelbrot(const char *name, QObect *parent=0); public slots: void start(); signals: void done(); private

29、slots: void calculate(); private: QTimer timer; ;,49,QObject類(lèi)(實(shí)例),/構(gòu)造初始化一個(gè)Mandelbrot對(duì)象 Mandelbrot:Mandelbrot(const char *name, QObject *parent) :QObject(parent, name) connect( ,50,信號(hào)/槽機(jī)制,51,回調(diào)函數(shù),回調(diào)函數(shù)是一個(gè)通過(guò)函數(shù)指針調(diào)用的函數(shù)。 如果把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個(gè)函數(shù),當(dāng)這個(gè)指針被用為調(diào)用它所指向的函數(shù)時(shí),我們就說(shuō)這是回調(diào)函數(shù)。 回調(diào)函數(shù)不是由該函數(shù)的實(shí)現(xiàn)方式直接調(diào)用,而是在特定的事件或

30、條件發(fā)生時(shí)由另外的一方調(diào)用的,用于對(duì)該事件或條件進(jìn)行響應(yīng)。,52,Signal/Slot機(jī)制,Qt程序中,事件處理的方式也是回調(diào),但與回調(diào)函數(shù)所不同的是,事件的發(fā)出和接收采用了信號(hào)(signal)和插槽(slot)機(jī)制,無(wú)須調(diào)用翻譯表,是類(lèi)型安全的回調(diào)。 類(lèi)似于觀察者設(shè)計(jì)模式 信號(hào)槽機(jī)制可以在對(duì)象之間彼此并不了解的情況下將它們的行為聯(lián)系起來(lái)。 槽函數(shù)能和信號(hào)相連接,只要信號(hào)發(fā)出了,這個(gè)槽函數(shù)就會(huì)自動(dòng)被調(diào)用。 利用信號(hào)和插槽進(jìn)行對(duì)象間的通信是Qt的最主要特征之一。,53,Signal/Slot機(jī)制(續(xù)),當(dāng)對(duì)象狀態(tài)發(fā)生改變的時(shí)候,發(fā)出signal通知所有的slot接收signal,盡管它并不知道

31、哪些函數(shù)定義了slot,而slot也同樣不知道要接收怎樣的signal signal和slot機(jī)制真正實(shí)現(xiàn)了封裝的概念,slot除了接收signal之外和其它的成員函數(shù)沒(méi)有什么不同 signal和slot之間是多對(duì)多的對(duì)應(yīng)關(guān)系。 在QObject中實(shí)現(xiàn),54,Signal/Slot實(shí)例,Qt程序的窗口部件發(fā)射信號(hào)(signals)來(lái)指出一個(gè)用戶(hù)的動(dòng)作或者是狀態(tài)的變化。 當(dāng)信號(hào)被發(fā)射的時(shí)候,和信號(hào)相連的槽就會(huì)自動(dòng)執(zhí)行。 “信號(hào)和槽”機(jī)制用于Qt對(duì)象間的通訊。,#include #include int main (int argc, char *argv ) QApplication app (

32、argc, argv); QPushButton *button = new QPushButton (“Qui”,0); QObject:connect (button, SIGNAL (clicked (), ,55,Signal和Slot的聲明,class Student : public QObject Q_OBJECT public: Student() myMark = 0; int mark() const return myMark; public slots: void setMark(int newMark); signals: void markChanged(int n

33、ewMark); private: int myMark; ;,在Qt程序設(shè)計(jì)中,凡是包含signal和slot的類(lèi)中都要加上Q_OBJECT宏定義 信號(hào)是一個(gè)類(lèi)的成員方法,該方法的實(shí)現(xiàn)是由meta-object自動(dòng)實(shí)現(xiàn)的 對(duì)于開(kāi)發(fā)者只需要在類(lèi)中聲明這個(gè)信號(hào),并不需要實(shí)現(xiàn)。 下面的例子給出了如何在一個(gè)類(lèi)中定義signal和slot:,56,Signal和Slot的聲明(續(xù)),void Student:setMark(int newMark) if (newMark!= myMark) myMark = newMark; emit markChanged(myMark); ,signal的發(fā)出一

34、般在事件的處理函數(shù)中,利用emit發(fā)出signal 在下面的例子中在在事件處理結(jié)束后發(fā)出signal,57,Signal和Slot的聲明(續(xù)),槽(slot)和普通的c+成員函數(shù)很像。 槽是類(lèi)的一個(gè)成員方法,當(dāng)信號(hào)觸發(fā)時(shí)該方法執(zhí)行。 可以是虛函數(shù)(virtual)、可被重載(overload)、可以是公有的(public)、保護(hù)的(protective)或者私有的(private)。 可以象任何c+成員函數(shù)一樣被直接調(diào)用,可以傳遞任何類(lèi)型的參數(shù),可以使用默認(rèn)參數(shù)。 槽不同于信號(hào),需要開(kāi)發(fā)者自己去實(shí)現(xiàn)。,58,什么是槽?,槽在各種槽段(section)中定義。 槽可以返回值,但并不是通過(guò)聯(lián)接。

35、任何數(shù)量的信號(hào)可以關(guān)聯(lián)到一個(gè)槽。 它以一個(gè)普通的函數(shù)實(shí)現(xiàn)。 它可以作為普通函數(shù)被調(diào)用。,public slots: void aPublicSlot(); protected slots: void aProtectedSlot(); private slots: void aPrivateSlot();,connect(src, SIGNAL(sig(), dest, SLOT(slt();,59,什么是信號(hào)?,信號(hào)在信號(hào)段(section)中定義 信號(hào)總是返回空 信號(hào)總是不必實(shí)現(xiàn) 由moc來(lái)提供實(shí)現(xiàn) 信號(hào)可以關(guān)聯(lián)到任意數(shù)量的槽上 通常產(chǎn)生一個(gè)直接調(diào)用,但是可以在線(xiàn)程之間作為事件來(lái)傳遞,甚至

36、可以用在套接字之間(使用第三方類(lèi)) 槽能以任意次序被激發(fā) 信號(hào)使用emit 關(guān)鍵字發(fā)射出去。,signals: void aSignal();,emit aSignal();,60,Signal和Slot的連接,bool QObject:connect(sender, SIGNAL(valueChanged(int), receiver, SLOT(display(int);,為了能夠接受到信號(hào),信號(hào)和槽需要使用connect()函數(shù)關(guān)聯(lián)起來(lái)。 connect()函數(shù)是QObject類(lèi)的成員函數(shù),它能夠連接signal和slot,也可以用來(lái)連接signal和signal 函數(shù)原形如下:,sen

37、der和receiver是QObject對(duì)象指針。 SIGNALE()和SLOT()宏的作用是把他們的參數(shù)轉(zhuǎn)換成字符串。,61,Signal和Slot的連接,bool QObject:connect(sender, SIGNAL(valueChanged(int), receiver, SLOT(display(int);,為了能夠接受到信號(hào),信號(hào)和槽需要使用connect()函數(shù)關(guān)聯(lián)起來(lái)。 connect()函數(shù)是QObject類(lèi)的成員函數(shù),它能夠連接signal和slot,也可以用來(lái)連接signal和signal 函數(shù)原形如下:,sender和receiver是QObject對(duì)象指針。 S

38、IGNALE()和SLOT()宏的作用是把他們的參數(shù)轉(zhuǎn)換成字符串。,62,Signal和Slot的連接(續(xù)),連接規(guī)則 一個(gè)信號(hào)可以連接到多個(gè)槽 多個(gè)信號(hào)可以連接到同一個(gè)槽 一個(gè)信號(hào)可以和另一個(gè)信號(hào)相連 連接可以被刪除 bool QObject:disconnect (sender, SIGNAL(valueChanged(int), receiver, SLOT(display(int) 這個(gè)函數(shù)很少使用,因?yàn)楫?dāng)一個(gè)對(duì)象被刪除后,Qt自動(dòng)刪除這個(gè)對(duì)象的所有連接,63,Signal和Slot的連接(續(xù)),connect()函數(shù)舉例:,QLabel *label = new QLabel; QS

39、crollBar *scroll = new QScrollBar; QObject:connect( scroll, SIGNAL(valueChanged(int), label, SLOT(setNum(int) );,64,Signal和Slot的連接(續(xù)),65,同一個(gè)信號(hào)連接多個(gè)插槽 connect(slider, SIGNAL(valueChanged(int), spinBox, SLOT(setValue(int); connect(slider, SIGNAL(valueChanged(int), this, SLOT(updateStatusBarIndicator(in

40、t); 多個(gè)信號(hào)連接到同一個(gè)插槽 connect(lcd, SIGNAL(overflow(), this, SLOT(handleMathError(); connect(calculator, SIGNAL(divisionByZero(), this, SLOT(handleMathError();,Signal和Slot的連接(續(xù)),66,一個(gè)信號(hào)連接到另一個(gè)信號(hào) connect(lineEdit, SIGNAL(textChanged(const QString 取消一個(gè)連接不是很常用,因?yàn)镼t會(huì)在一個(gè)對(duì)象被刪除后自動(dòng)取消這個(gè)對(duì)象所包含的所有的連接,Signal和Slot的連接(續(xù))

41、,67,信號(hào)與槽機(jī)制深入,信號(hào)發(fā)生后 如果信號(hào)和槽實(shí)現(xiàn)在同一個(gè)線(xiàn)程中,當(dāng)信號(hào)產(chǎn)生的時(shí)候,與它關(guān)聯(lián)的槽就會(huì)馬上得到執(zhí)行 如果信號(hào)和槽不在同一個(gè)線(xiàn)程中,槽的執(zhí)行可能會(huì)有延遲(next event loop) 相關(guān)聯(lián)的信號(hào)和槽必須滿(mǎn)足一定條件 信號(hào)的參數(shù)可以多于槽的參數(shù),多余的參數(shù)被忽略,反之則不行 信號(hào)和槽函數(shù)必須有著相同的參數(shù)類(lèi)型及順序 不會(huì)有編譯時(shí)的錯(cuò)誤檢查, 運(yùn)行時(shí)檢查 如果參數(shù)類(lèi)型不匹配,或者信號(hào)和槽不存在,應(yīng)用程序在debug狀態(tài)下時(shí),Qt會(huì)在運(yùn)行期間給出警告。 如果信號(hào)和槽連接時(shí)包含了參數(shù)的名字,Qt也將會(huì)給出警告。,68,信號(hào)與槽機(jī)制深入(續(xù)),signal和slot只是對(duì)于回調(diào)函數(shù)

42、一個(gè)比較安全的封裝(wrapper) slot對(duì)應(yīng)回調(diào)函數(shù),signal則相當(dāng)于觸發(fā)回調(diào)函數(shù)的方法。 但QApplication可以模擬異步的方式。 如果程序只是簡(jiǎn)單使用Qt的基本類(lèi),或者從QtObject派生而來(lái)的自定義類(lèi),而不是QApplication的話(huà),肯定不是異步機(jī)制 實(shí)驗(yàn):在emit之后printf(“emitn”);在slot中printf(“slotn”),結(jié)果是首先打印slot然后emit,這就表明了emit調(diào)用陷入了slot中。 qApp在事件循環(huán)處理中截取所有emit的signal,然后調(diào)用相應(yīng)的slots,就像回調(diào)函數(shù)一樣,69,建立關(guān)聯(lián),QObject:connect

43、( src, SIGNAL( signature ), dest, SLOT( signature ) );, ( . ),clicked() toggled(bool) setText(QString) textChanged(QString) rangeChanged(int,int),setTitle(QString text) setValue(42),簽名由函數(shù)名和參數(shù)類(lèi)型組成。不允許有變量名或值。,自定義類(lèi)型降低了可重用性,setItem(ItemClass),70,建立關(guān)聯(lián),Qt 參數(shù)可以忽略,但不能無(wú)中生有。,Signals rangeChanged(int,int) rang

44、eChanged(int,int) rangeChanged(int,int) valueChanged(int) valueChanged(int) valueChanged(int) textChanged(QString) clicked() clicked(),Slots setRange(int,int) setValue(int) updateDialog() setRange(int,int) setValue(int) updateDialog() setValue(int) setValue(int) updateDialog(),71,自動(dòng)關(guān)聯(lián),使用Qt Designer,

45、它很便捷地在接口和用戶(hù)代碼之間提供自動(dòng)關(guān)聯(lián)。 通過(guò)調(diào)用QMetaObject:connectSlotsByName觸發(fā) 當(dāng)命名時(shí)考慮重用性 比較 on_widget_signal 和 updatePageMargins,on_ object name _ signal name ( signal parameters ) on_addButton_clicked(); on_deleteButton_clicked(); on_listWidget_currentItemChanged(QListWidgetItem*,QListWidgetItem*),72,Signal/Slot鏈接舉例,

46、int main(int argc, char *argv) QApplication app(argc, argv); QPushButton *button = new QPushButton(Quit); QObject:connect(button, SIGNAL(clicked(), Qt程序的窗口部件發(fā)射信號(hào)(signals)來(lái)指出一個(gè)用戶(hù)的動(dòng)作或者是狀態(tài)的變化。當(dāng)信號(hào)被發(fā)射的時(shí)候,和信號(hào)相連的槽就會(huì)自動(dòng)執(zhí)行?!靶盘?hào)和槽”機(jī)制用于Qt對(duì)象間的通訊。,73,值同步,雙向連接 無(wú)限循環(huán)必須停止 沒(méi)有信號(hào)被發(fā)射,除非發(fā)生實(shí)際的變化。,void QDial:setValue(int v)

47、if(v=m_value) return; .,74,自定義信號(hào)和槽,class AngleObject : public QObject Q_OBJECT Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged) public: AngleObject(qreal angle, QObject *parent = 0); qreal angle() const; public slots: void setAngle(qreal); signals: void angleChanged(qreal); priv

48、ate: qreal m_angle; ;,75,setter實(shí)現(xiàn)細(xì)節(jié),void AngleObject:setAngle(qreal angle) if(m_angle = angle) return; m_angle = angle; emit angleChanged(m_angle); ,76,與值關(guān)聯(lián)?,一種常見(jiàn)情況是,希望在關(guān)聯(lián)聲明中傳遞一個(gè)值。 例如, 鍵盤(pán)實(shí)例 這不是有效的 -它將不會(huì)關(guān)聯(lián)。,connect(key, SIGNAL(clicked(), this, SLOT(keyPressed(1);,77,與值關(guān)聯(lián)?,解決方法 #1: 多個(gè)槽, . public slots

49、: void key1Pressed(); void key2Pressed(); void key3Pressed(); void key4Pressed(); void key5Pressed(); void key6Pressed(); void key7Pressed(); void key8Pressed(); void key9Pressed(); void key0Pressed(); . ,78,與值關(guān)聯(lián)?,解決方法 #2: 子類(lèi)發(fā)射器和增加信號(hào),QPushButton,QIntPushButton, . signals: void clicked(int); . , QInt

50、PushButton *b; b=new QIntPushButton(1); connect(b, SIGNAL(clicked(int), this, SLOT(keyPressed(int); b=new QIntPushButton(2); connect(b, SIGNAL(clicked(int), this, SLOT(keyPressed(int); b=new QIntPushButton(3); connect(b, SIGNAL(clicked(int), this, SLOT(keyPressed(int); . ,79,解決方案評(píng)價(jià),#1: 多個(gè)槽 許多槽包含幾乎相同

51、的代碼 難于維護(hù) (一個(gè)小的變化影響所有槽) 難于擴(kuò)展 (每次都要新建槽) #2:子類(lèi)發(fā)射器和增加信號(hào) 額外的專(zhuān)用類(lèi) (難于重用) 難于擴(kuò)展 (每個(gè)情況需新建子類(lèi)),80,信號(hào)映射器,QSignalMapper 類(lèi)解決了這個(gè)問(wèn)題 將每個(gè)值映射到每個(gè)發(fā)射器 介于可重用類(lèi)之間, QSignalMapper *m = QSignalMapper(this); QPushButton *b; b=new QPushButton(1); connect(b, SIGNAL(clicked(), m, SLOT(map(); m-setMapping(b, 1); . connect(m, SIGNAL(

52、mapped(int), this, SLOT(keyPressed(int); ,81,信號(hào)映射器,QSignalMapper, . public slots: void keyPressed(); . ,信號(hào)映射器把每一個(gè)按鈕和值關(guān)聯(lián)起來(lái)。這些值都被映射。 當(dāng)一個(gè)值被映射,映射器發(fā)出攜帶關(guān)聯(lián)的值的映射信號(hào)(int)。,82,簡(jiǎn)單實(shí)例:溫度轉(zhuǎn)換器,83,溫度轉(zhuǎn)換器,使用 TempConverter 類(lèi)實(shí)現(xiàn)在攝氏與華氏之間的轉(zhuǎn)換 當(dāng)溫度改變時(shí)發(fā)射信號(hào)。,84,溫度轉(zhuǎn)換器,對(duì)話(huà)窗口(dialog window)包含以下對(duì)象 一個(gè) TempConverter 實(shí)例 兩個(gè) QGroupBox 部件(

53、widget), 每一個(gè)包含 一個(gè) QDial 部件 一個(gè) QLCDNumber 部件,85,溫度轉(zhuǎn)換器,class TempConverter : public QObject Q_OBJECT public: TempConverter(int tempCelsius, QObject *parent = 0); int tempCelsius() const; int tempFahrenheit() const; public slots: void setTempCelsius(int); void setTempFahrenheit(int); signals: void temp

54、CelsiusChanged(int); void tempFahrenheitChanged(int); private: int m_tempCelsius; ;,86,setTempCelsius槽: setTempFahrenheit槽:,溫度轉(zhuǎn)換器,void TempConverter:setTempCelsius(int tempCelsius) if(m_tempCelsius = tempCelsius) return; m_tempCelsius = tempCelsius; emit tempCelsiusChanged(m_tempCelsius); emit tempF

55、ahrenheitChanged(tempFahrenheit(); void TempConverter:setTempFahrenheit(int tempFahrenheit) int tempCelsius = (5.0/9.0)*(tempFahrenheit-32); setTempCelsius(tempCelsius); ,87,溫度轉(zhuǎn)換器,表盤(pán)通過(guò) TempConverter 聯(lián)系起來(lái) LCD 顯示直接受表盤(pán)來(lái)驅(qū)動(dòng)。,connect(celsiusDial, SIGNAL(valueChanged(int), tempConverter, SLOT(setTempCelsiu

56、s(int); connect(celsiusDial, SIGNAL(valueChanged(int), celsiusLcd, SLOT(display(int); connect(tempConverter, SIGNAL(tempCelsiusChanged(int), celsiusDial, SLOT(setValue(int); connect(fahrenheitDial, SIGNAL(valueChanged(int), tempConverter, SLOT(setTempFahrenheit(int); connect(fahrenheitDial, SIGNAL(v

57、alueChanged(int), fahrenheitLcd, SLOT(display(int); connect(tempConverter, SIGNAL(tempFahrenheitChanged(int), fahrenheitDial, SLOT(setValue(int);,88,溫度轉(zhuǎn)換器,用戶(hù)調(diào)節(jié)攝氏度表盤(pán)。,connect(celsiusDial, SIGNAL(valueChanged(int), tempConverter, SLOT(setTempCelsius(int); connect(celsiusDial, SIGNAL(valueChanged(int),

58、 celsiusLcd, SLOT(display(int); connect(tempConverter, SIGNAL(tempCelsiusChanged(int), celsiusDial, SLOT(setValue(int); connect(fahrenheitDial, SIGNAL(valueChanged(int), tempConverter, SLOT(setTempFahrenheit(int); connect(fahrenheitDial, SIGNAL(valueChanged(int), fahrenheitLcd, SLOT(display(int); connect(tempConverter, SIGNAL

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論