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

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quá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編譯過程,5,Qt編譯過程,方法一:直接通過Qt IDE(Qt Creator)界面直接編譯 方法二:命令行編譯 執(zhí)行“qmake -project” 創(chuàng)建 Qt 工程文件(.pro),該工程文件也可以手動創(chuàng)建 執(zhí)行“qmake” 缺省輸入為工程文件,產(chǎn)生平臺相關的 Makefile(s) 產(chǎn)生編譯規(guī)則,為工程中包含有 Q_OBJECT 宏的頭文件調(diào)用 moc 編譯器 執(zhí)行“make” 編譯程序 執(zhí)行moc, uic和rcc,6,Qt編譯工具:moc, uic 和 rcc,moc, 元對象(

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

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

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

6、Font() 用來設置字體 事件處理:sendEvent() 用來發(fā)送事件 GUI風格:setStyles() 設置圖形用戶界面的風格 顏色使用:colorSpec() 用來返回顏色文件 文本處理:translate() 用來處理文本信息 創(chuàng)建組件:setmainWidget() 用來設置窗口的主組件 ,15,16,程序退出,退出事件程序,只需要在程序結(jié)束時返回一個exec(),例如: return app.exec(); 其中app為QApplication的實例,當調(diào)用exec()將進入主事件的循環(huán)中,直到exit()被調(dià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類負責程序退出,退出應用程序可以調(diào)用繼承自QCoreApplication類的quit或exit函數(shù) QApplication是QCoreApplication類的子類 quit ():告訴應用程序退出,并返回0(表示成功) exit(0):同quit() 舉例 QPushButton *quitButton

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

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

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

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

12、信息(QObject:classInfo),25,元數(shù)據(jù),元數(shù)據(jù)通過元對象編譯器(moc)在編譯時組合在一起。,sources *.cpp,executables,object files *.o,headers *.h,普通的C+生成過程,includes,compiles,links,26,元數(shù)據(jù)Meta data,元數(shù)據(jù)通過元對象編譯器(moc)在編譯時組合在一起。 moc從頭文件里面獲得數(shù)據(jù)。,sources *.cpp,executables,object files *.o,headers *.h,generated moc_*.cpp,Qt C+ 生成過程,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),類在運行時了解它們自己的信息 對實現(xiàn)腳本和動態(tài)語言的綁定有很好的支持。,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 對于布爾類型: 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ù)? 可以驗證設置 對可能的變化作出反應,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),屬性跟類中數(shù)據(jù)成員的主要區(qū)別 必須有一個read函數(shù) 有一個可選的write函數(shù) 如果定義了stored屬性表明這是一直存在的。 一個reset函數(shù)能夠把property設置成其默認狀態(tài) 一個designable屬性表明該property能在GUI builder(一般為Qt Designer)可見 注意: Q_PROPERTY 主要用于Qt Designer plugin (插件)開發(fā)中,33,使用屬性,直接獲取 通過元信息和屬性系統(tǒng) 在運行時發(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,動態(tài)屬性,在運行時給對象增加屬性 可以用來“標識”對象,等等。,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對象樹及內(nèi)存管理,39,QObject類(續(xù))-父子關系,每一個QObject對象都可以有一個指向父親的參數(shù) 孩子會通知他的父親自己的存在,父親會把它加入到自己的孩子列表中 如果一個widget對象沒有父親,那么他就是一個窗口 父部件可以: 當父部件隱藏或顯示自己的時候,會自動的隱藏和顯示子部件 當父部件enable和disable時,子部件的狀態(tài)也隨之變化 注意:在父部件可見的時候,子部件也可以單獨隱藏自己,40,改變所有者,QObject可以修改它所屬的父對象。 父對象知道何時子對象被刪除 一系列函

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

23、管理都轉(zhuǎn)移給了父對象 使用new在堆上分配內(nèi)存 子對象可自動被父對象刪除內(nèi)存 手動刪除不會引起二次刪除,因為子對象刪除時會通知父對象 沒有父對象的QObject對象都需要手動刪除 一般把這種無父親的對象分配在棧上,可以避免內(nèi)存泄露的問題 Qt是否有類似于自動回收站的機制?但是事實是沒有的! 只需要關注對象的父子關系和功能!,42,內(nèi)存管理,QObject 可以有父對象和子對象 當一個父對象被刪除,它的子對象也同樣被刪除。,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)存管理,當需要實現(xiàn)視覺層級時使用到它,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指針指向最高層父對象 在棧上分配父對象空間,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 都有一個默認為空值的父對象。 QWidget 的父對象是其它 QWidget類 為了方便傾向于提供多種構(gòu)造(包括只帶有父對象的一種) 父對象通常是帶缺省值的第一個參數(shù)。,QLabel(const QString ,QObject(QObject *parent=0);,Q

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

28、創(chuàng)建帶有父對象及其名字的對象,對象的父對象可以看作這個對象的所有者。比如,對話框是其中的ok和cancel按鈕的父對象。 在上面的函數(shù)中如果parent為0則構(gòu)造一個無父的對象,如果對象是一個組件,則它就會成為頂層的窗口。,48,QObject類(實例),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類(實例),/構(gòu)造初始化一個Mandelbrot對象 Mandelbrot:Mandelbrot(const char *name, QObject *parent) :QObject(parent, name) connect( ,50,信號/槽機制,51,回調(diào)函數(shù),回調(diào)函數(shù)是一個通過函數(shù)指針調(diào)用的函數(shù)。 如果把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個函數(shù),當這個指針被用為調(diào)用它所指向的函數(shù)時,我們就說這是回調(diào)函數(shù)。 回調(diào)函數(shù)不是由該函數(shù)的實現(xiàn)方式直接調(diào)用,而是在特定的事件或

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

31、哪些函數(shù)定義了slot,而slot也同樣不知道要接收怎樣的signal signal和slot機制真正實現(xiàn)了封裝的概念,slot除了接收signal之外和其它的成員函數(shù)沒有什么不同 signal和slot之間是多對多的對應關系。 在QObject中實現(xiàn),54,Signal/Slot實例,Qt程序的窗口部件發(fā)射信號(signals)來指出一個用戶的動作或者是狀態(tài)的變化。 當信號被發(fā)射的時候,和信號相連的槽就會自動執(zhí)行。 “信號和槽”機制用于Qt對象間的通訊。,#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程序設計中,凡是包含signal和slot的類中都要加上Q_OBJECT宏定義 信號是一個類的成員方法,該方法的實現(xiàn)是由meta-object自動實現(xiàn)的 對于開發(fā)者只需要在類中聲明這個信號,并不需要實現(xiàn)。 下面的例子給出了如何在一個類中定義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ù)很像。 槽是類的一個成員方法,當信號觸發(fā)時該方法執(zhí)行。 可以是虛函數(shù)(virtual)、可被重載(overload)、可以是公有的(public)、保護的(protective)或者私有的(private)。 可以象任何c+成員函數(shù)一樣被直接調(diào)用,可以傳遞任何類型的參數(shù),可以使用默認參數(shù)。 槽不同于信號,需要開發(fā)者自己去實現(xiàn)。,58,什么是槽?,槽在各種槽段(section)中定義。 槽可以返回值,但并不是通過聯(lián)接。

35、任何數(shù)量的信號可以關聯(lián)到一個槽。 它以一個普通的函數(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,什么是信號?,信號在信號段(section)中定義 信號總是返回空 信號總是不必實現(xiàn) 由moc來提供實現(xiàn) 信號可以關聯(lián)到任意數(shù)量的槽上 通常產(chǎn)生一個直接調(diào)用,但是可以在線程之間作為事件來傳遞,甚至

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

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

38、IGNALE()和SLOT()宏的作用是把他們的參數(shù)轉(zhuǎn)換成字符串。,62,Signal和Slot的連接(續(xù)),連接規(guī)則 一個信號可以連接到多個槽 多個信號可以連接到同一個槽 一個信號可以和另一個信號相連 連接可以被刪除 bool QObject:disconnect (sender, SIGNAL(valueChanged(int), receiver, SLOT(display(int) 這個函數(shù)很少使用,因為當一個對象被刪除后,Qt自動刪除這個對象的所有連接,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,同一個信號連接多個插槽 connect(slider, SIGNAL(valueChanged(int), spinBox, SLOT(setValue(int); connect(slider, SIGNAL(valueChanged(int), this, SLOT(updateStatusBarIndicator(in

40、t); 多個信號連接到同一個插槽 connect(lcd, SIGNAL(overflow(), this, SLOT(handleMathError(); connect(calculator, SIGNAL(divisionByZero(), this, SLOT(handleMathError();,Signal和Slot的連接(續(xù)),66,一個信號連接到另一個信號 connect(lineEdit, SIGNAL(textChanged(const QString 取消一個連接不是很常用,因為Qt會在一個對象被刪除后自動取消這個對象所包含的所有的連接,Signal和Slot的連接(續(xù))

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

42、一個比較安全的封裝(wrapper) slot對應回調(diào)函數(shù),signal則相當于觸發(fā)回調(diào)函數(shù)的方法。 但QApplication可以模擬異步的方式。 如果程序只是簡單使用Qt的基本類,或者從QtObject派生而來的自定義類,而不是QApplication的話,肯定不是異步機制 實驗:在emit之后printf(“emitn”);在slot中printf(“slotn”),結(jié)果是首先打印slot然后emit,這就表明了emit調(diào)用陷入了slot中。 qApp在事件循環(huán)處理中截取所有emit的signal,然后調(diào)用相應的slots,就像回調(diào)函數(shù)一樣,69,建立關聯(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ù)類型組成。不允許有變量名或值。,自定義類型降低了可重用性,setItem(ItemClass),70,建立關聯(lián),Qt 參數(shù)可以忽略,但不能無中生有。,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,自動關聯(lián),使用Qt Designer,

45、它很便捷地在接口和用戶代碼之間提供自動關聯(lián)。 通過調(diào)用QMetaObject:connectSlotsByName觸發(fā) 當命名時考慮重用性 比較 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ā)射信號(signals)來指出一個用戶的動作或者是狀態(tài)的變化。當信號被發(fā)射的時候,和信號相連的槽就會自動執(zhí)行?!靶盘柡筒邸睓C制用于Qt對象間的通訊。,73,值同步,雙向連接 無限循環(huán)必須停止 沒有信號被發(fā)射,除非發(fā)生實際的變化。,void QDial:setValue(int v)

47、if(v=m_value) return; .,74,自定義信號和槽,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實現(xiàn)細節(jié),void AngleObject:setAngle(qreal angle) if(m_angle = angle) return; m_angle = angle; emit angleChanged(m_angle); ,76,與值關聯(lián)?,一種常見情況是,希望在關聯(lián)聲明中傳遞一個值。 例如, 鍵盤實例 這不是有效的 -它將不會關聯(lián)。,connect(key, SIGNAL(clicked(), this, SLOT(keyPressed(1);,77,與值關聯(lián)?,解決方法 #1: 多個槽, . public slots

49、: void key1Pressed(); void key2Pressed(); void key3Pressed(); void key4Pressed(); void key5Pressed(); void key6Pressed(); void key7Pressed(); void key8Pressed(); void key9Pressed(); void key0Pressed(); . ,78,與值關聯(lián)?,解決方法 #2: 子類發(fā)射器和增加信號,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,解決方案評價,#1: 多個槽 許多槽包含幾乎相同

51、的代碼 難于維護 (一個小的變化影響所有槽) 難于擴展 (每次都要新建槽) #2:子類發(fā)射器和增加信號 額外的專用類 (難于重用) 難于擴展 (每個情況需新建子類),80,信號映射器,QSignalMapper 類解決了這個問題 將每個值映射到每個發(fā)射器 介于可重用類之間, 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,信號映射器,QSignalMapper, . public slots: void keyPressed(); . ,信號映射器把每一個按鈕和值關聯(lián)起來。這些值都被映射。 當一個值被映射,映射器發(fā)出攜帶關聯(lián)的值的映射信號(int)。,82,簡單實例:溫度轉(zhuǎn)換器,83,溫度轉(zhuǎn)換器,使用 TempConverter 類實現(xiàn)在攝氏與華氏之間的轉(zhuǎn)換 當溫度改變時發(fā)射信號。,84,溫度轉(zhuǎn)換器,對話窗口(dialog window)包含以下對象 一個 TempConverter 實例 兩個 QGroupBox 部件(

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

評論

0/150

提交評論