Qt類庫和信號槽.ppt_第1頁
Qt類庫和信號槽.ppt_第2頁
Qt類庫和信號槽.ppt_第3頁
Qt類庫和信號槽.ppt_第4頁
Qt類庫和信號槽.ppt_第5頁
已閱讀5頁,還剩89頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、,9/23/2020,1,Qt類庫,Qt類庫架構(gòu),Qt類庫,跨平臺的qt包含了大約15個模塊 接近700個APIs, 所有的模塊都依賴于QtCore 特殊情況,有3個模塊依賴具體的平臺: QAxContainer、QAxServer、QtDBus,9/23/2020,3,9/23/2020,4,5,Qt類庫(續(xù)),9/23/2020,6,Qt主要基類,QObject類,Qt對象模型的核心 QObject類 是幾乎所有Qt類和所有部件(widget)的基類 所有的QWidgets都是QObject 提供對象樹和對象的關(guān)系 QObject在整個Qt的體系中處于一個非常重要的位置 提供了信號-槽的通

2、信機制 對象不允許拷貝(禁用拷貝構(gòu)造) 包含了很多組成Qt的機制 事件處理 內(nèi)存管理 屬性,內(nèi)省(Introspection),9/23/2020,7,元數(shù)據(jù)(Meta data),Qt用C+實現(xiàn)內(nèi)?。↖ntrospection) 每一個 QObject 都有一個元對象 元對象涉及: 類名 (QObject:className) 繼承 (QObject:inherits) 屬性 信號和槽 普通信息(QObject:classInfo),元數(shù)據(jù),元數(shù)據(jù)通過元對象編譯器(moc)在編譯時組合在一起。,sources *.cpp,executables,object files *.o,header

3、s *.h,普通的C+生成過程,includes,compiles,links,元數(shù)據(jù)Meta data,元數(shù)據(jù)通過元對象編譯器(moc)在編譯時組合在一起。 moc從頭文件里面獲得數(shù)據(jù)。,sources *.cpp,executables,object files *.o,headers *.h,generated moc_*.cpp,Qt C+ 生成過程,includes,compiles,links,compiles,mocs,元數(shù)據(jù),moc 找什么?,class MyClass : public QObject Q_OBJECT Q_CLASSINFO(author, John Doe

4、) public: MyClass(const Foo ,內(nèi)省(Introspection),類在運行時了解它們自己的信息 對實現(xiàn)腳本和動態(tài)語言的綁定有很好的支持。,if (object-inherits(QAbstractItemView) QAbstractItemView *view = static_cast(widget); view-. enum CapitalsEnum Oslo, Helsinki, Stockholm, Copenhagen ; int index = object-metaObject()-indexOfEnumerator(CapitalsEnum); o

5、bject-metaObject()-enumerator(index)-key(object-capital();,屬性(Properties),QObject有g(shù)etter和setter函數(shù)屬性 命名策略: color, setColor 對于布爾類型: isEnabled, setEnabled,class QLabel : public QFrame Q_OBJECT Q_PROPERTY(QString text READ text WRITE setText) public: QString text() const; public slots: void setText(cons

6、t QString ,屬性,為什么使用setter 函數(shù)? 可以驗證設(shè)置 對可能的變化作出反應(yīng),void setMin( int newMin ) if( newMin m_max ) qWarning(Ignoring setMin(%d) as min max., newMin); return; .,void setMin( int newMin ) . m_min = newMin; updateMinimum(); ,屬性,為什么使用getter 函數(shù)? 間接的屬性,QSize size() const return m_size; int width() const return

7、m_size.width(); ,屬性,Q_PROPERTY(type name READ getFunction WRITE setFunction RESET resetFunction NOTIFY notifySignal DESIGNABLE bool SCRIPTABLE bool STORED bool USER bool CONSTANT FINAL),屬性跟類中數(shù)據(jù)成員的主要區(qū)別 必須有一個read函數(shù) 有一個可選的write函數(shù) 如果定義了stored屬性表明這是一直存在的。 一個reset函數(shù)能夠把property設(shè)置成其默認(rèn)狀態(tài) 一個desinable屬性表明該prop

8、erty能在GUI builder(一般為Qt Designer)可見,使用屬性,直接獲取 通過元信息和屬性系統(tǒng) 在運行時發(fā)現(xiàn)屬性,QString text = label-text(); label-setText(Hello World!);,QString text = object-property(text).toString(); object-setProperty(text, Hello World);,int QMetaObject:propertyCount(); QMetaProperty QMetaObject:property(i); QMetaProperty:na

9、me/isConstant/isDesignable/read/write/.,動態(tài)屬性,在運行時給對象增加屬性 可以用來“標(biāo)識”對象,等等。,bool ret = object-setProperty(name, value);,QObject:dynamicPropertyNames() const,創(chuàng)建自定義屬性,class AngleObject : public QObject Q_OBJECT Q_PROPERTY(qreal angle READ angle WRITE setAngle) public: AngleObject(qreal angle, QObject *par

10、ent = 0); qreal angle() const; void setAngle(qreal); private: qreal m_angle; ;,創(chuàng)建自定義屬性,AngleObject:AngleObject(qreal angle, QObject *parent) : QObject(parent), m_angle(angle) qreal AngleObject:angle() const return m_angle; void AngleObject:setAngle(qreal angle) m_angle = angle; doSomething(); ,自定義屬性

11、 - 枚舉,class AngleObject : public QObject Q_OBJECT Q_ENUMS(AngleMode) Q_PROPERTY(AngleMode angleMode READ .) public: enum AngleMode Radians, Degrees; . ;,QObject類(續(xù))-父子關(guān)系,每一個QObject對象都可以有一個指向父親的參數(shù) 孩子會通知他的父親自己的存在,父親會把它加入到自己的孩子列表中 如果一個widget對象沒有父親,那么他就是一個窗口 父部件可以: 當(dāng)父部件隱藏或顯示自己的時候,會自動的隱藏和顯示子部件 當(dāng)父部件enable

12、和disable時,子部件的狀態(tài)也隨之變化 注意:在父部件可見的時候,子部件也可以單獨隱藏自己,9/23/2020,22,改變所有者,QObject可以修改它所屬的父對象。 父對象知道何時子對象被刪除 一系列函數(shù)實現(xiàn)返回指針,從其所有者“拿走”釋放的數(shù)據(jù),把它留給拿取者處理,obj-setParent(newParent);,delete listWidget-item(0); / 刪除第一個item(不安全),QLayoutItem *QLayout:takeAt(int); QListWidgetItem *QListWidget:takeItem(int); / Safe alterna

13、tive QListWidgetItem *item = listWidget-takeItem(0); if (item) delete item; ,QObject類(續(xù))-內(nèi)存管理,所有子對象的內(nèi)存管理都轉(zhuǎn)移給了父對象 使用new在堆上分配內(nèi)存 子對象可自動被父對象刪除內(nèi)存 手動刪除不會引起二次刪除,因為子對象刪除時會通知父對象 沒有父對象的QObject對象都需要手動刪除 一般把這種無父親的對象分配在棧上,可以避免內(nèi)存泄露的問題 Qt是否有類似于自動回收站的機制?但是事實是沒有的! 只需要關(guān)注對象的父子關(guān)系和功能!,9/23/2020,24,內(nèi)存管理,QObject 可以有父對象和子對

14、象 當(dāng)一個父對象被刪除,它的子對象也同樣被刪除。,QObject *parent = new QObject(); QObject *child1 = new QObject(parent); QObject *child2 = new QObject(parent); QObject *child1_1 = new QObject(child1); QObject *child1_2 = new QObject(child1); delete parent;,parent,child1,child2,child1_1,child1_2,內(nèi)存管理,當(dāng)需要實現(xiàn)視覺層級時使用到它。,QDialog

15、 *parent = new QDialog(); QGroupBox *box = new QGroupBox(parent); QPushButton *button = new QPushButton(parent); QRadioButton *option1 = new QRadioButton(box); QRadioButton *option2 = new QRadioButton(box); delete parent;,使用模式,使用 this指針指向最高層父對象 在棧上分配父對象空間,void Widget:showDialog() Dialog dialog; if (

16、dialog.exec() = QDialog:Accepted) . ,Dialog:Dialog(QWidget *parent) : QDialog(parent) QGroupBox *box = QGroupBox(this); QPushButton *button = QPushButton(this); QRadioButton *option1 = QRadioButton(box); QRadioButton *option2 = QRadioButton(box); .,堆(Heap),當(dāng)使用 new 和 delete時, 內(nèi)存在堆中分配。 堆內(nèi)存空間必須通過 delet

17、e 完全釋放,以防止內(nèi)存泄漏。 只要有需要,分配在堆上的對象可以一直存活下去。,new,delete,構(gòu)造Construction,析構(gòu)Destruction,棧(Stack),局部變量在棧上分配。 棧變量超過作用范圍時會自動釋放。 分配在棧中的對象在超出作用范圍時總是會被析構(gòu)。,int a,構(gòu)造Construction,析構(gòu)Destruction,堆和棧,想要自動內(nèi)存管理,只有父對象需要在棧上分配。,MyMainWindow,QApplication,int main(int argc, char *argv) QApplication a(argc, argv); MyMainWindow

18、 w; w.show(); return a.exec(); ,MyMainWindow:MyMainWindow(. new QLabel(this); new . ,QObject類(續(xù))-創(chuàng)建對象,從QObject繼承的對象都使用new在堆上分配空間 如果創(chuàng)建對象的時候設(shè)置了父對象,父對象就負(fù)責(zé)管理新創(chuàng)建的對象 QLabel *label = new QLabel(”Some Text”, parent); 沒有從QObject繼承的對象則分配在棧上,而不是堆上 QStringList list; QColor color; 例外 QFile和QApplication (繼承QObjec

19、t) 通常分配在棧上 模式對話框常常分配在棧上,9/23/2020,31,構(gòu)造規(guī)范,幾乎所有的 QObject 都有一個默認(rèn)為空值的父對象。 QWidget 的父對象是其它 QWidget類 為了方便傾向于提供多種構(gòu)造(包括只帶有父對象的一種) 父對象通常是帶缺省值的第一個參數(shù)。,QLabel(const QString ,QObject(QObject *parent=0);,QPushButton(QWidget *parent=0); QPushButton(const QString ,構(gòu)造規(guī)范,當(dāng)創(chuàng)建自己的 QObject時, 需考慮 總是允許父對象 parent 為 0 (null

20、) 有一個只接受父對象的構(gòu)造函數(shù) parent 是帶默認(rèn)值的第一個參數(shù) 提供幾種構(gòu)造函數(shù),避免空值、無效值(e.g. QString()作為參數(shù)。,QObject類對象,QObject類是所有能夠處理signal、slot和事件的Qt對象的基類,原形如下: QObject:QObject ( QObject*parent =0,constchar*name = 0 ) 創(chuàng)建帶有父對象及其名字的對象,對象的父對象可以看作這個對象的所有者。比如,對話框是其中的ok和cancel按鈕的父對象。 在上面的函數(shù)中如果parent為0則構(gòu)造一個無父的對象,如果對象是一個組件,則它就會成為頂層的窗口。,9/

21、23/2020,34,QObject類(實例),9/23/2020,35,class Mandelbrot:public QObject Q_OBJECT /需要使用signal和slot public: Mandelbrot(QObect *parent=0, const char *name); public slots: void start(); signals: void done(); private slots: void calculate(); private: QTimer timer; ;,36,QObject類(實例),/構(gòu)造初始化一個Mandelbrot對象 Mand

22、elbrot:Mandelbrot(QObject *parent=0, const char *name) :QObject(parent, name) connect( ,QApplication類,QApplication類負(fù)責(zé)GUI應(yīng)用程序的控制流和主要的設(shè)置,包括: 主事件循環(huán)體,負(fù)責(zé)處理和調(diào)度所有來自窗口系統(tǒng)和其他資源的事件 處理應(yīng)用程序的開始、結(jié)束以及會話管理 還包括系統(tǒng)和應(yīng)用程序方面的設(shè)置 對于一個應(yīng)用程序來說,建立QApplication類的對象是必不可少的 QApplication是QObject類的子類,9/23/2020,37,38,QWidget類,QWidget類是

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

24、inWindow或者一個QDialog作為程序界面,但是Qt允許任何窗口部件成為窗口。 當(dāng)窗口部件被創(chuàng)建的時候,它總是隱藏的,必須調(diào)用show()來使它可見。 QWidget類有很多成員函數(shù),但一般不直接使用,而是通過子類繼承來使用其函數(shù)功能。如,QPushButton、QlistBox等都是它的子類,9/23/2020,40,41,9/23/2020,42,Qt程序要素,初始化QApplication,在Qt應(yīng)用程序中,首先要創(chuàng)建一個QApplication對象 QApplication類負(fù)責(zé)圖形用戶界面應(yīng)用程序的控制流和主要設(shè)置 在main.cpp中定義如下: int main(int a

25、rgc, char *argv) QApplication a(argc, argv); ,9/23/2020,43,初始化 QApplication,QApplication包含主事件循環(huán)體,對所有來自窗口系統(tǒng)和其它資源的事件進(jìn)行處理和調(diào)度,還包括處理應(yīng)用程序的初始化和結(jié)束,并且提供會話管理,處理絕大多數(shù)系統(tǒng)范圍和應(yīng)用程序范圍的設(shè)置。 在Qt應(yīng)用程序中,不管有多少個窗口,QApplication對象只能有一個,而且必須在其他對象之前創(chuàng)建,可以利用全局指針qApp訪問QApplication對象。 QApplication類中封裝了很多函數(shù),其中包括: 系統(tǒng)設(shè)置:setFont() 用來設(shè)置字

26、體 事件處理:sendEvent() 用來發(fā)送事件 GUI風(fēng)格:setStyles() 設(shè)置圖形用戶界面的風(fēng)格 顏色使用:colorSpec() 用來返回顏色文件 文本處理:translate() 用來處理文本信息 創(chuàng)建組件:setmainWidget() 用來設(shè)置窗口的主組件 ,9/23/2020,44,退出 QApplication,退出應(yīng)用程序可以調(diào)用繼承自QCoreApplication的quit函數(shù)或exit函數(shù) QApplication是QCoreApplication類的子類 quit ():告訴應(yīng)用程序退出,并返回0(表示成功) exit(0):同quit() 舉例 QPush

27、Button *quitButton = new QPushButton(Quit); connect(quitButton, SIGNAL(clicked(), qApp, SLOT(quit(); 或 qApp-exit(0);,9/23/2020,45,退出 QApplication,調(diào)用QApplication:closeAllWindows () 尤其適用于有多個頂層窗口的應(yīng)用程序 如果關(guān)閉窗口后,不想讓應(yīng)用程序退出,則需要調(diào)用函數(shù) QApplication:setQuitOnLastWindowClosed (false) 舉例 exitAct = new QAction(tr(E

28、,9/23/2020,46,創(chuàng)建窗口,在Qt程序中,創(chuàng)建窗口比較簡單,只要在main.cpp文件中為ApplicationWindow建立一個指針: ApplicationWindow *mw = new ApplicatonWindow(); ApplicationWindow是在Application.h中定義的類,它是一個QMainWindow的子類,9/23/2020,47,創(chuàng)建組件,組件的創(chuàng)建需要調(diào)用相應(yīng)組件的類,并在頭文件中包含此類的頭文件或者創(chuàng)建自定義類,繼承組件類的功能 #include “qpushbutton.h” class hello:public QWidget he

29、llo類繼承了QWidget類的特征,并加入了自定義的特征功能,同樣需要在頭文件中包含此類的頭文件 在main.cpp的函數(shù)中需要創(chuàng)建hello類的實例,或創(chuàng)建QPushButton類的實例,才可以使用 hello h(string); QPushButton hello(“Hello,world!”,0);,9/23/2020,48,創(chuàng)建組件(續(xù)),如果組件本身可以作為主窗口,則無需設(shè)置主窗口。在上例中,按鈕創(chuàng)建時其構(gòu)造函數(shù)中的第二個參數(shù)為0,表示按鈕所在窗口為主窗口,不需要設(shè)置主窗口。否則需要調(diào)用QWidget成員函數(shù)setMainWidget()來進(jìn)行設(shè)置 h.setMainWidget

30、(,9/23/2020,49,事件,在X程序中,敲擊鍵盤,鼠標(biāo)指針在窗口中的移動或鼠標(biāo)按鍵動作等,都是事件 在Xt中提供了一種叫做回調(diào)的事件處理方式。 通過翻譯表,將事件映射為相應(yīng)的動作,當(dāng)組件得到事件通知,就去表中找出相應(yīng)的動作例程進(jìn)行處理。 這種機制需要應(yīng)用程序注冊有關(guān)組件的回調(diào)函數(shù)或普通的事件處理函數(shù),以分發(fā)循環(huán)Xt的事件,9/23/2020,50,事件(續(xù)),Qt事件的處理過程 QApplication的事件循環(huán)體從事件隊列中拾取本地窗口系統(tǒng)事件或其他事件 譯成QEvent(),并送給QObject:event(),最后送給QWidget:event()分別對事件處理,9/23/202

31、0,51,9/23/2020,52,Signal/Slot事件處理機制,回調(diào)函數(shù),回調(diào)函數(shù)是一個通過函數(shù)指針調(diào)用的函數(shù)。 如果把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個函數(shù),當(dāng)這個指針被用為調(diào)用它所指向的函數(shù)時,我們就說這是回調(diào)函數(shù)。 回調(diào)函數(shù)不是由該函數(shù)的實現(xiàn)方式直接調(diào)用,而是在特定的事件或條件發(fā)生時由另外的一方調(diào)用的,用于對該事件或條件進(jìn)行響應(yīng)。,9/23/2020,53,Signal/Slot機制,Qt程序中,事件處理的方式也是回調(diào),但與回調(diào)函數(shù)所不同的是,事件的發(fā)出和接收采用了信號(signal)和插槽(slot)機制,無須調(diào)用翻譯表,是類型安全的回調(diào)。 類似于觀察者設(shè)計模式 信號槽機制

32、可以在對象之間彼此并不了解的情況下將它們的行為聯(lián)系起來。 槽函數(shù)能和信號相連接,只要信號發(fā)出了,這個槽函數(shù)就會自動被調(diào)用。 利用信號和插槽進(jìn)行對象間的通信是Qt的最主要特征之一。,9/23/2020,54,Signal/Slot機制(續(xù)),當(dāng)對象狀態(tài)發(fā)生改變的時候,發(fā)出signal通知所有的slot接收signal,盡管它并不知道哪些函數(shù)定義了slot,而slot也同樣不知道要接收怎樣的signal signal和slot機制真正實現(xiàn)了封裝的概念,slot除了接收signal之外和其它的成員函數(shù)沒有什么不同 signal和slot之間是多對多的對應(yīng)關(guān)系。 在QObject中實現(xiàn),9/23/20

33、20,55,Signal/Slot實例,Qt程序的窗口部件發(fā)射信號(signals)來指出一個用戶的動作或者是狀態(tài)的變化。 當(dāng)信號被發(fā)射的時候,和信號相連的槽就會自動執(zhí)行。 “信號和槽”機制用于Qt對象間的通訊。,9/23/2020,56,#include #include int main (int argc, char *argv ) QApplication app (argc, argv); QPushButton *button = new QPushButton (“Qui”,0); QObject:connect (button, SIGNAL (clicked (), ,57,

34、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 newMark); private: int myMark; ;,在Qt程序設(shè)計中,凡是包含signal和slot的類中都要加上Q_OBJECT的定義 信號是一個類的成員方法,該方法的實現(xiàn)是由meta-object自動實現(xiàn)的

35、 對于開發(fā)者只需要在類中聲明這個信號,并不需要實現(xiàn)。 下面的例子給出了如何在一個類中定義signal和slot:,58,Signal和Slot的聲明(續(xù)),void Student:setMark(int newMark) if (newMark!= myMark) myMark = newMark; emit markChanged(myMark); ,signal的發(fā)出一般在事件的處理函數(shù)中,利用emit發(fā)出signal 在下面的例子中在在事件處理結(jié)束后發(fā)出signal,59,Signal和Slot的聲明(續(xù)),槽(slot)和普通的c+成員函數(shù)很像。 槽是類的一個成員方法,當(dāng)信號觸發(fā)時該

36、方法執(zhí)行。 可以是虛函數(shù)(virtual)、可被重載(overload)、可以是公有的(public)、保護(hù)的(protective)或者私有的(private)。 可以象任何c+成員函數(shù)一樣被直接調(diào)用,可以傳遞任何類型的參數(shù),可以使用默認(rèn)參數(shù)。 槽不同于信號,需要開發(fā)者自己去實現(xiàn)。,什么是槽?,槽在各種槽段(section)中定義。 槽可以返回值,但并不是通過聯(lián)接。 任何數(shù)量的信號可以關(guān)聯(lián)到一個槽。 它以一個普通的函數(shù)實現(xiàn)。 它可以作為普通函數(shù)被調(diào)用。,public slots: void aPublicSlot(); protected slots: void aProtectedSlot

37、(); private slots: void aPrivateSlot();,connect(src, SIGNAL(sig(), dest, SLOT(slt();,什么是信號?,信號在信號段(section)中定義 信號總是返回空 信號總是不必實現(xiàn) 由moc來提供實現(xiàn) 信號可以關(guān)聯(lián)到任意數(shù)量的槽上 通常產(chǎn)生一個直接調(diào)用,但是可以在線程之間作為事件來傳遞,甚至可以用在套接字之間(使用第三方類) 槽能以任意次序被激發(fā) 信號使用emit 關(guān)鍵字發(fā)射出去。,signals: void aSignal();,emit aSignal();,62,Signal和Slot的連接,bool QObjec

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

39、lueChanged(int), receiver, SLOT(display(int);,為了能夠接受到信號,信號和槽需要使用connect()函數(shù)關(guān)聯(lián)起來。 connect()函數(shù)是QObject類的成員函數(shù),它能夠連接signal和slot,也可以用來連接signal和signal 函數(shù)原形如下:,sender和receiver是QObject對象指針。 SIGNALE()和SLOT()宏的作用是把他們的參數(shù)轉(zhuǎn)換成字符串。,64,Signal和Slot的連接(續(xù)),連接規(guī)則 一個信號可以連接到多個槽 多個信號可以連接到同一個槽 一個信號可以和另一個信號相連 連接可以被刪除 bool QO

40、bject:disconnect (sender, SIGNAL(valueChanged(int), receiver, SLOT(display(int) 這個函數(shù)很少使用,因為當(dāng)一個對象被刪除后,Qt自動刪除這個對象的所有連接,Signal和Slot的連接(續(xù)),connect()函數(shù)舉例:,9/23/2020,65,QLabel *label = new QLabel; QScrollBar *scroll = new QScrollBar; QObject:connect( scroll, SIGNAL(valueChanged(int), label, SLOT(setNum(in

41、t) );,9/23/2020,66,Signal和Slot的連接(續(xù)),67,同一個信號連接多個插槽 connect(slider, SIGNAL(valueChanged(int), spinBox, SLOT(setValue(int); connect(slider, SIGNAL(valueChanged(int), this, SLOT(updateStatusBarIndicator(int); 多個信號連接到同一個插槽 connect(lcd, SIGNAL(overflow(), this, SLOT(handleMathError(); connect(calculator

42、, SIGNAL(divisionByZero(), this, SLOT(handleMathError();,Signal和Slot的連接(續(xù)),68,一個信號連接到另一個信號 connect(lineEdit, SIGNAL(textChanged(const QString 取消一個連接不是很常用,因為Qt會在一個對象被刪除后自動取消這個對象所包含的所有的連接,Signal和Slot的連接(續(xù)),信號與槽機制深入,信號發(fā)生后 如果信號和槽實現(xiàn)在同一個線程中,當(dāng)信號產(chǎn)生的時候,與它關(guān)聯(lián)的槽就會馬上得到執(zhí)行 如果信號和槽不在同一個線程中,槽的執(zhí)行可能會有延遲(next event loop

43、) 相關(guān)聯(lián)的信號和槽必須滿足一定條件 信號的參數(shù)可以多于槽的參數(shù),多余的參數(shù)被忽略,反之則不行 信號和槽函數(shù)必須有著相同的參數(shù)類型及順序 不會有編譯時的錯誤檢查, 運行時檢查 如果參速類型不匹配,或者信號和槽不存在,應(yīng)用程序在debug狀態(tài)下時,Qt會在運行期間給出警告。 如果信號和槽連接時包含了參數(shù)的名字,Qt也將會給出警告。,信號與槽機制深入(續(xù)),signal和slot只是對于回調(diào)函數(shù)一個比較安全的封裝(wrapper) slot對應(yīng)回調(diào)函數(shù),signal則相當(dāng)于觸發(fā)回調(diào)函數(shù)的方法。 但QApplication可以模擬異步的方式。 如果程序只是簡單使用Qt的基本類,或者從QtObject

44、派生而來的自定義類,而不是QApplication的話,肯定不是異步機制 實驗:在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ù)一樣,建立關(guān)聯(lián),QObject:connect( src, SIGNAL( signature ), dest, SLOT( signature ) );, ( . ),clicked() toggled(bool) setText(QString) tex

45、tChanged(QString) rangeChanged(int,int),setTitle(QString text) setValue(42),簽名由函數(shù)名和參數(shù)類型組成。不允許有變量名或值。,自定義類型降低了可重用性,setItem(ItemClass),建立關(guān)聯(lián),Qt 參數(shù)可以忽略,但不能無中生有。,Signals rangeChanged(int,int) rangeChanged(int,int) rangeChanged(int,int) valueChanged(int) valueChanged(int) valueChanged(int) textChanged(QSt

46、ring) clicked() clicked(),Slots setRange(int,int) setValue(int) updateDialog() setRange(int,int) setValue(int) updateDialog() setValue(int) setValue(int) updateDialog(),自動關(guān)聯(lián),使用Designer,它很便捷地在接口和用戶代碼之間提供自動關(guān)聯(lián)。 通過調(diào)用QMetaObject:connectSlotsByName觸發(fā) 當(dāng)命名時考慮重用性 比較 on_widget_signal 和 updatePageMargins,on_ o

47、bject name _ signal name ( signal parameters ) on_addButton_clicked(); on_deleteButton_clicked(); on_listWidget_currentItemChanged(QListWidgetItem*,QListWidgetItem*),值同步,雙向連接 無限循環(huán)必須停止 沒有信號被發(fā)射,除非發(fā)生實際的變化。,void QDial:setValue(int v) if(v=m_value) return; .,自定義信號和槽,class AngleObject : public QObject Q_O

48、BJECT 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); private: qreal m_angle; ;,setter實現(xiàn)細(xì)節(jié),void AngleObject:setAngle(qreal angle) i

49、f(m_angle = angle) return; m_angle = angle; emit angleChanged(m_angle); ,溫度轉(zhuǎn)換器,使用 TempConverter 類實現(xiàn)在攝氏與華氏之間的轉(zhuǎn)換 當(dāng)溫度改變時發(fā)射信號。,溫度轉(zhuǎn)換器,對話窗口(dialog window)包含以下對象 一個 TempConverter 實例 兩個 QGroupBox 部件(widget), 每一個包含 一個 QDial 部件 一個 QLCDNumber 部件,溫度轉(zhuǎn)換器,class TempConverter : public QObject Q_OBJECT public: TempC

50、onverter(int tempCelsius, QObject *parent = 0); int tempCelsius() const; int tempFahrenheit() const; public slots: void setTempCelsius(int); void setTempFahrenheit(int); signals: void tempCelsiusChanged(int); void tempFahrenheitChanged(int); private: int m_tempCelsius; ;,溫度轉(zhuǎn)換器,void TempConverter:set

51、TempCelsius(int tempCelsius) if(m_tempCelsius = tempCelsius) return; m_tempCelsius = tempCelsius; emit tempCelsiusChanged(m_tempCelsius); emit tempFahrenheitChanged(tempFahrenheit(); void TempConverter:setTempFahrenheit(int tempFahrenheit) int tempCelsius = (5.0/9.0)*(tempFahrenheit-32); setTempCels

52、ius(tempCelsius); ,setTempCelsius槽: setTempFahrenheit槽:,溫度轉(zhuǎn)換器,表盤通過 TempConverter 聯(lián)系起來 LCD 顯示直接受表盤來驅(qū)動。,connect(celsiusDial, SIGNAL(valueChanged(int), tempConverter, SLOT(setTempCelsius(int); connect(celsiusDial, SIGNAL(valueChanged(int), celsiusLcd, SLOT(display(int); connect(tempConverter, SIGNAL(te

53、mpCelsiusChanged(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(tempFahrenheitChanged(int), fahrenhe

54、itDial, SLOT(setValue(int);,溫度轉(zhuǎn)換器,用戶調(diào)節(jié)攝氏度表盤。,connect(celsiusDial, SIGNAL(valueChanged(int), tempConverter, SLOT(setTempCelsius(int); connect(celsiusDial, SIGNAL(valueChanged(int), celsiusLcd, SLOT(display(int); connect(tempConverter, SIGNAL(tempCelsiusChanged(int), celsiusDial, SLOT(setValue(int); c

55、onnect(fahrenheitDial, SIGNAL(valueChanged(int), tempConverter, SLOT(setTempFahrenheit(int); connect(fahrenheitDial, SIGNAL(valueChanged(int), fahrenheitLcd, SLOT(display(int); connect(tempConverter, SIGNAL(tempFahrenheitChanged(int), fahrenheitDial, SLOT(setValue(int);,溫度轉(zhuǎn)換器,用戶調(diào)節(jié)攝氏度表盤。,connect(cels

56、iusDial, SIGNAL(valueChanged(int), tempConverter, SLOT(setTempCelsius(int); connect(celsiusDial, SIGNAL(valueChanged(int), celsiusLcd, SLOT(display(int); connect(tempConverter, SIGNAL(tempCelsiusChanged(int), celsiusDial, SLOT(setValue(int); connect(fahrenheitDial, SIGNAL(valueChanged(int), tempConv

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

58、tTempCelsius(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(valueChanged(int), fahrenheitLcd, SLOT(display(int)

溫馨提示

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

最新文檔

評論

0/150

提交評論