




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
.Qt的對象模型和信號槽的概念QtinEducation.Qt的對象模型QtinEducationThisworkisaChinesetranslationoftheoriginalQtEducationalTrainingMaterialspublishedbyNokia:?2010NokiaCorporationanditsSubsidiary(-ies).Nokia,QtandtheNokiaandQtlogosaretheregisteredtrademarksofNokiaCorporationinFinlandandothercountriesworldwide.ThistranslationwascreatedbyCommunicationandComputerNetworkLaboratoryofGuangdongProvince,SouthChinaUniversityofTechnology.?2010CommunicationandComputerNetworkLaboratoryofGuangdongProvince,SouthChinaUniversityofTechnology.TheenclosedQtEducationalTrainingMaterialsareprovidedundertheCreativeCommonsAttribution-Non-Commercial-ShareAlike2.5LicenseAgreement.Thefulllicensetextisavailablehere:./licenses/by-nc-sa/2.5/legalcode.
此文檔內容是由諾基亞公司發(fā)布的原創(chuàng)Qt教育培訓文檔的中文翻譯:?2010諾基亞公司及其附屬公司。Nokia(諾基亞),Qt以及Nokia與Qt商標是Nokia公司在芬蘭和全球其他國家的注冊商標。
該翻譯版本由華南理工大學廣東省計算機網絡重點實驗室創(chuàng)造。?2010華南理工大學廣東省計算機網絡重點實驗室
本Qt教育培訓材料依照署名-非商業(yè)性使用-相同方式共享2.5許可協議(CreativeCommons
Attribution-Non-Commercial-ShareAlike2.5LicenseAgreement)發(fā)布。
完整的許可證文本可以在這里找到:./licenses/by-nc-sa/2.5/legalcode。
Qt的對象模型與信號槽的概念課件QObject類QObject是幾乎所有Qt類和所有部件(widget)的基類。它包含很多組成Qt的機制事件信號和槽屬性內存管理QObject類QObject是幾乎所有Qt類和所有部件(wQObject類QObject
是大部分Qt類的基類例外的例子是:類需要作為輕量級的類,例如圖元(graphicalprimitives)。數據容器(QString,QList,QChar等)需要可復制的類,因為QObject類是無法被復制的。QObject類QObject是大部分Qt類的基類QObject類它們可以擁有一個名字
(QObject::objectName)它們被放置在QObject實例的一個層次上它們可以有到其他
QObject
實例的聯接例子:在運行時復制一個部件有意義嗎?“QObject的實例是單獨的!”QObject類它們可以擁有一個名字(QObject::o元數據(Metadata)Qt用C++實現內省每一個
QObject
都有一個元對象元對象涉及:類名
(QObject::className)繼承
(QObject::inherits)屬性信號和槽普通信息(QObject::classInfo)元數據(Metadata)Qt用C++實現內省元數據元數據通過元對象編譯器(moc)在編譯時組合在一起。sources*.cppexecutablesobjectfiles*.oheaders*.h普通的C++生成過程includescompileslinks元數據元數據通過元對象編譯器(moc)在編譯時組合在一起。s元數據Metadata元數據通過元對象編譯器(moc)在編譯時組合在一起。moc從頭文件里面獲得數據。sources*.cppexecutablesobjectfiles*.oheaders*.hgeneratedmoc_*.cppQtC++生成過程includescompileslinkscompilesmocs元數據Metadata元數據通過元對象編譯器(moc)在編元數據moc找什么?classMyClass:publicQObject{
Q_OBJECTQ_CLASSINFO("author","JohnDoe")public:MyClass(constFoo&foo,QObject*parent=0);Foofoo()const;publicslots:voidsetFoo(constFoo&foo);signals:voidfooChanged(Foo);private:Foom_foo;};Qt關鍵字類的一般信息Q_OBJECT宏,
通常是第一步首先確認該類繼承自
Qobject(可能是間接)元數據moc找什么?classMyClass:pub內省(Introspection)類在運行時了解它們自己的信息對實現腳本和動態(tài)語言的綁定有很好的支持。if(object->inherits("QAbstractItemView")){QAbstractItemView*view=static_cast<QAbstractItemView*>(widget);view->...enumCapitalsEnum{Oslo,Helsinki,Stockholm,Copenhagen};intindex=object->metaObject()->indexOfEnumerator("CapitalsEnum");object->metaObject()->enumerator(index)->key(object->capital());能夠實現動態(tài)轉換而不需要運行時類型檢查(
RTTI)例子:它可以將枚舉值轉換成更容易閱讀和保存的字符串元對象了解細節(jié)內省(Introspection)類在運行時了解它們自己的信屬性(Properties)QObject有getter和setter函數屬性命名策略:color,setColor對于布爾:isEnabled,setEnabledclassQLabel:publicQFrame{Q_OBJECTQ_PROPERTY(QStringtextREADtextWRITEsetText)public:QStringtext()const;publicslots:voidsetText(constQString&);};Setter,返回空,將值當成唯一參數Getter,常量,返回值,沒有參數屬性(Properties)QObject有getter和s屬性為什么使用setter函數?可以驗證設置對可能的變化作出反應voidsetMin(intnewMin){if(newMin>m_max){qWarning("IgnoringsetMin(%d)asmin>max.",newMin);return;}...voidsetMin(intnewMin){...m_min=newMin;updateMinimum();}屬性為什么使用setter函數?voidsetMin(屬性Properties為什么使用getter函數?間接的屬性QSizesize()const{returnm_size;}intwidth()const{returnm_size.width();}屬性Properties為什么使用getter函數?QSi屬性Q_PROPERTY(typenameREADgetFunction[WRITEsetFunction][RESETresetFunction]
[NOTIFYnotifySignal][DESIGNABLEbool][SCRIPTABLEbool][STOREDbool][USERbool][CONSTANT][FINAL])屬性Q_PROPERTY(typename使用屬性直接獲取通過元信息和屬性系統在運行時發(fā)現屬性QStringtext=label->text();label->setText("HelloWorld!");QStringtext=object->property("text").toString();object->setProperty("text","HelloWorld");intQMetaObject::propertyCount();QMetaPropertyQMetaObject::property(i);QMetaProperty::name/isConstant/isDesignable/read/write/...使用屬性直接獲取QStringtext=label->動態(tài)屬性在運行時給對象增加屬性可以用來“標識”對象,等等。boolret=object->setProperty(name,value);QObject::dynamicPropertyNames()const真:如果屬性經過Q_PROPERTY定義
假:如果只是動態(tài)增加返回一個動態(tài)屬性的列表動態(tài)屬性在運行時給對象增加屬性boolret=obje創(chuàng)建自定義屬性classAngleObject:publicQObject{Q_OBJECTQ_PROPERTY(qrealangleREADangleWRITEsetAngle)public:AngleObject(qrealangle,QObject*parent=0);qrealangle()const;voidsetAngle(qreal);private:qrealm_angle;};宏,描述屬性初始化值GetterSetter私有狀態(tài)創(chuàng)建自定義屬性classAngleObject:pub創(chuàng)建自定義屬性AngleObject::AngleObject(qrealangle,QObject*parent):QObject(parent),m_angle(angle){}qrealAngleObject::angle()const{returnm_angle;}voidAngleObject::setAngle(qrealangle){m_angle=angle;doSomething();}初始化值Getter簡單返回值。這里你可以計算復雜的值。更新內部狀態(tài),對變化作出反應。創(chuàng)建自定義屬性AngleObject::AngleObjec自定義屬性-枚舉classAngleObject:publicQObject{Q_OBJECTQ_ENUMS(AngleMode)Q_PROPERTY(AngleModeangleModeREAD...)public:enumAngleMode{Radians,Degrees};...};普通枚舉聲明。宏通知QtAngleMode是一個枚舉類型。屬性使用枚舉作為類型。自定義屬性-枚舉classAngleObject:內存管理QObject
可以有父對象和子對象當一個父對象被刪除,它的子對象也同樣被刪除。QObject*parent=newQObject();QObject*child1=newQObject(parent);QObject*child2=newQObject(parent);QObject*child1_1=newQObject(child1);QObject*child1_2=newQObject(child1);deleteparent;parentchild1child2child1_1child1_2parent刪除
child1和
child2child1刪除
child1_1和
child1_2內存管理QObject可以有父對象和子對象QObject內存管理當需要實現視覺層級時使用到它。QDialog*parent=newQDialog();QGroupBox*box=newQGroupBox(parent);QPushButton*button=newQPushButton(parent);QRadioButton*option1=newQRadioButton(box);QRadioButton*option2=newQRadioButton(box);deleteparent;parent刪除
box和
buttonbox刪除
option1和
option2內存管理當需要實現視覺層級時使用到它。QDialog*pa使用模式使用
this指針指向最高層父對象在棧上分配父對象空間voidWidget::showDialog(){Dialogdialog;if(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);...dialog
在作用范圍結束時被刪除使用模式使用this指針指向最高層父對象voidWidg堆(Heap)當使用
new
和
delete時,內存在堆中分配。堆內存空間必須通過delete完全釋放,以防止內存泄漏。只要有需要,分配在堆上的對象可以一直存活下去。newdelete構造Construction析構Destruction堆(Heap)當使用new和delete時,內存在堆棧(Stack)局部變量在棧上分配。棧變量超過作用范圍時會自動釋放。分配在棧中的對象在超出作用范圍時總是會被析構。inta}構造Construction析構Destruction棧(Stack)局部變量在棧上分配。inta}構造Cons堆和棧想要自動內存管理,只有父對象需要在棧上分配。MyMainWindowQApplicationintmain(intargc,char**argv){QApplicationa(argc,argv);MyMainWindoww;w.show();returna.exec();}MyMainWindow::MyMainWindow(...{newQLabel(this);new...}堆和棧想要自動內存管理,只有父對象需要在棧上分配。MyM改變所有者QObject可以修改它所屬的父對象。父對象知道何時子對象被刪除一系列函數實現返回指針,從其所有者“拿走”釋放的數據,把它留給拿取者處理obj->setParent(newParent);deletelistWidget->item(0);//刪除第一個item(不安全)QLayoutItem*QLayout::takeAt(int);QListWidgetItem*QListWidget::takeItem(int);//SafealternativeQListWidgetItem*item=listWidget->takeItem(0);if(item){deleteitem;}item列表本質上并不是子對象,而是擁有者。
這個例子進行了說明。改變所有者QObject可以修改它所屬的父對象。obj->s構造規(guī)范幾乎所有的QObject都有一個默認為空值的父對象。Qwidget
的父對象是其它
QWidget類為了方便傾向于提供多種構造(包括只帶有父對象的一種)父對象通常是帶缺省值的第一個參數。QLabel(constQString&text,QWidget*parent=0,Qt::WindowFlagsf=0);QObject(QObject*parent=0);QPushButton(QWidget*parent=0);QPushButton(constQString&text,QWidget*parent=0);QPushButton(constQIcon&icon,constQString&text,QWidget*parent=0);構造規(guī)范幾乎所有的QObject都有一個默認為空值的父對構造規(guī)范當創(chuàng)建自己的
Qobject時,需考慮總是允許父對象
parent
為
0(null)有一個只接受父對象的構造函數parent
是帶默認值的第一個參數提供幾種構造函數,避免空值、無效值(e.g.QString())作為參數。構造規(guī)范當創(chuàng)建自己的Qobject時,需考慮休息休息信號(signal)和槽(slot)通過反饋的方式動態(tài)地或松散地將事件和狀態(tài)變化聯系起來。是什么使
Qt運作?信號(signal)和槽(slot)通過反饋的方式動態(tài)地或松動作中的信號和槽emitclicked();動作中的信號和槽emitclicked();動作中的信號和槽privateslots:voidon_addButton_clicked();voidon_deleteButton_clicked();connect(clearButton,SIGNAL(clicked()),listWidget,SLOT(clear()));connect(addButton,SIGNAL(clicked()),this,SLOT(...));2xclear();動作中的信號和槽privateslots:connect(動作中的信號和槽{...emitclicked();...}{...emitclicked();...}{...emitclicked();...}{QStringnewText=QInputDialog::getText(this,"Entertext","Text:");if(!newText.isEmpty())ui->listWidget->addItem(newText);}{foreach(QListWidgetItem*item,ui->listWidget->selectedItems()){deleteitem;}}clear();動作中的信號和槽{{{{{clear();信號和槽vs回調回調(callback)是一個函數指針,當一個事件發(fā)生時被調用,任何函數都可以被安排作為回調。沒有類型安全總是以直接調用方式工作信號和槽的方式更加動態(tài)一個更通用的機制更容易互連兩個已存在的類相關類之間涉及更少的知識共享信號和槽vs回調回調(callback)是一個函數指針,什么是槽?槽在各種槽段(section)中定義。槽可以返回值,但并不是通過聯接。任何數量的信號可以關聯到一個槽。它以一個普通的函數實現。它可以作為普通函數被調用。publicslots:voidaPublicSlot();protectedslots:voidaProtectedSlot();privateslots:voidaPrivateSlot();connect(src,SIGNAL(sig()),dest,SLOT(slt()));什么是槽?槽在各種槽段(section)中定義。public什么是信號?信號在信號段(section)中定義信號總是返回空信號總是不必實現由moc來提供實現信號可以關聯到任意數量的槽上通常產生一個直接調用,但是可以在線程之間作為事件來傳遞,甚至可以用在套接字之間(使用第三方類)
槽能以任意次序被激發(fā)信號使用emit關鍵字發(fā)射出去。signals:voidaSignal();emitaSignal();什么是信號?信號在信號段(section)中定義signal建立關聯QObject::connect(src,SIGNAL(signature),dest,SLOT(signature));<functionname>(<argtype>...)clicked()toggled(bool)setText(QString)textChanged(QString)rangeChanged(int,int)setTitle(QStringtext)setValue(42)簽名由函數名和參數類型組成。不允許有變量名或值。自定義類型降低了可重用性QObject*setItem(ItemClass)建立關聯QObject::connect(src,SIG建立關聯Qt參數可以忽略,但不能無中生有。SignalsrangeChanged(int,int)rangeChanged(int,int)rangeChanged(int,int)valueChanged(int)valueChanged(int)valueChanged(int)textChanged(QString)clicked()clicked()SlotssetRange(int,int)setValue(int)updateDialog()setRange(int,int)setValue(int)updateDialog()setValue(int)setValue(int)updateDialog()建立關聯Qt參數可以忽略,但不能無中生有。SignalsS自動關聯使用Designer,它很便捷地在接口和用戶代碼之間提供自動關聯。通過調用QMetaObject::connectSlotsByName觸發(fā)當命名時考慮重用性比較
on_widget_signal
和
updatePageMarginson_objectname
_signalname
(signalparameters
)on_addButton_clicked();on_deleteButton_clicked();on_listWidget_currentItemChanged(QListWidgetItem*,QListWidgetItem*)updatePageMargins
可以關聯到一定數量信號或直接調用。自動關聯使用Designer,它很便捷地在接口和用戶代碼之間值同步雙向連接無限循環(huán)必須停止——沒有信號被發(fā)射,除非發(fā)生實際的變化。connect(dial1,SIGNAL(valueChanged(int)),dial2,SLOT(setValue(int)));connect(dial2,SIGNAL(valueChanged(int)),dial1,SLOT(setValue(int)));voidQDial::setValue(intv){if(v==m_value)return;...這就是負責發(fā)射信號的所有代碼—在您自己的類中不要忘記它。值同步雙向連接connect(dial1,SIGNAL(v自定義信號和槽classAngleObject:publicQObject{Q_OBJECTQ_PROPERTY(qrealangleREADangleWRITEsetAngleNOTIFYangleChanged)public:AngleObject(qrealangle,QObject*parent=0);qrealangle()const;publicslots:voidsetAngle(qreal);signals:voidangleChanged(qreal);private:qrealm_angle;};在這里添加一個通知信號。setter構造自然槽。信號匹配setter自定義信號和槽classAngleObject:pubsetter實現細節(jié)voidAngleObject::setAngle(qrealangle){if(m_angle==angle)return;m_angle=angle;emitangleChanged(m_angle);}防止無限循環(huán)。不要忘記!更新內部狀態(tài),然后發(fā)射信號。信號是被“保護”的,他們可以從派生類發(fā)射。setter實現細節(jié)voidAngleObject::se溫度轉換器使用
TempConverter
類實現在攝氏與華氏之間的轉換當溫度改變時發(fā)射信號。溫度轉換器使用TempConverter類實現在攝氏與華溫度轉換器對話窗口(dialogwindow)包含以下對象一個
TempConverter
實例兩個
QGroupBox
部件(widget),每一個包含一個
QDial
部件一個
QLCDNumber
部件溫度轉換器對話窗口(dialogwindow)包含以下對象溫度轉換器classTempConverter:publicQObject{Q_OBJECT
public:TempConverter(inttempCelsius,QObject*parent=0);inttempCelsius()const;inttempFahrenheit()const;publicslots:voidsetTempCelsius(int);voidsetTempFahrenheit(int);signals:voidtempCelsiusChanged(int);voidtempFahrenheitChanged(int);private:intm_tempCelsius;};先是Q_OBJECT宏QObject作為父對象父對象指針讀和寫函數當溫度變化時發(fā)射信號。在內部表示整數攝氏度。溫度轉換器classTempConverter:pub溫度轉換器voidTempConverter::setTempCelsius(inttempCelsius){if(m_tempCelsius==tempCelsius)return;m_tempCelsius=tempCelsius;emittempCelsiusChanged(m_tempCelsius);emittempFahrenheitChanged(tempFahrenheit());}voidTempConverter::setTempFahrenheit(inttempFahrenheit){inttempCelsius=(5.0/9.0)*(tempFahrenheit-32);setTempCelsius(tempCelsius);}setTempCelsius槽:setTempFahrenheit槽:測試改變以中斷遞歸更新對象的狀態(tài)發(fā)射信號反映改變轉換,傳遞攝氏度是內部表現形式。溫度轉換器voidTempConverter::setTe溫度轉換器表盤通過
TempConverter
聯系起來LCD顯示直接受表盤來驅動。TempConvertersetTempCelsiussetTempFahrenheittempCelsiusChangedtempFahrenheitChangedvalueChanged→setTempCelsiusvalueChanged→setTempFahrenheittempCelsiusChanged→setValuetempFahrenheitChanged→setValuevalueChanged→displayconnect(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)));connect(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)));溫度轉換器表盤通過TempConverter聯系起來Te溫度轉換器用戶調節(jié)攝氏度表盤。TempConvertersetTempCelsiussetTempFahrenheittempCelsiusChangedtempFahrenheitChangedvalueChanged→setTempCelsiusvalueChanged→setTempFahrenheittempCelsiusChanged→setValuetempFahrenheitChanged→setValuevalueChanged→displayconnect(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)));connect(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)));溫度轉換器用戶調節(jié)攝氏度表盤。TempConverterva溫度轉換器用戶調節(jié)攝氏度表盤。TempConvertersetTempCelsiussetTempFahrenheittempCelsiusChangedtempFahrenheitChangedvalueChanged→setTempCelsiusvalueChanged→setTempFahrenheittempCelsiusChanged→setValuetempFahrenheitChanged→setValuevalueChanged→displayconnect(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)));connect(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)));溫度轉換器用戶調節(jié)攝氏度表盤。TempConverterva溫度轉換器用戶調節(jié)攝氏度表盤。TempConvertersetTempCelsiussetTempFahrenheittempCelsiusChangedtempFahrenheitChangedvalueChanged→setTempCelsiusvalueChanged→setTempFahrenheittempCelsiusChanged→setValuetempFahrenheitChanged→setValuevalueChanged→displayconnect(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)));connect(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)));溫度轉換器用戶調節(jié)攝氏度表盤。TempConverterva溫度轉換器用戶調節(jié)攝氏度表盤。TempConvertersetTempCelsiussetTempFahrenheittempCelsiusChangedtempFahrenheitChangedvalueChanged→setTempCelsiusvalueChanged→setTempFahrenheittempCelsiusChanged→setValuetempFahrenheitChanged→setValuevalueChanged→displayconnect(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)));connect(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)));溫度轉換器用戶調節(jié)攝氏度表盤。TempConverterva溫度轉換器用戶調節(jié)攝氏度表盤。TempConvertersetTempCelsiussetTempFahrenheittempCelsiusChangedtempFahrenheitChangedvalueChanged→setTempCelsiusvalueChanged→setTempFahrenheittempCelsiusChanged→setValuetempFahrenheitChanged→setValuevalueChanged→displayconnect(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)));connect(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)));溫度轉換器用戶調節(jié)攝氏度表盤。TempConverterva溫度轉換器用戶調節(jié)攝氏度表盤。TempConvertersetTempCelsiussetTempFahrenheittempCelsiusChangedtempFahrenheitChangedvalueChanged→setTempCelsiusvalueChanged→setTempFahrenheittempCelsiusChanged→setValuetempFahrenheitChanged→setValuevalueChanged→displayconnect(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)));connect(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)));溫度轉換器用戶調節(jié)攝氏度表盤。TempConverterva溫度轉換器用戶調節(jié)攝氏度表盤。TempConvertersetTempCelsiussetTempFahrenheittempCelsiusChangedtempFahrenheitChangedvalueChanged→setTempCelsiusvalueChanged→setTempFahrenheittempCelsiusChanged→setValuetempFahrenheitChanged→setValuevalueChanged→displayconnect(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)));connect(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)));溫度轉換器用戶調節(jié)攝氏度表盤。TempConverterva與值關聯?一種常見情況是,希望在關聯聲明中傳遞一個值。例如,鍵盤實例這不是有效的--它將不會關聯。connect(key,SIGNAL(clicked()),this,SLOT(keyPressed(1)));與值關聯?一種常見情況是,希望在關聯聲明中傳遞一個值。con與值關聯?解決方法
#1:多個槽{...publicslots:voidkey1Pressed();voidkey2Pressed();voidkey3Pressed();voidkey4Pressed();voidkey5Pressed();voidkey6Pressed();voidkey7Pressed();voidkey8Pressed();voidkey9Pressed();voidkey0Pressed();...}connections與值關聯?解決方法#1:多個槽{connections與值關聯?解決方法
#2:子類發(fā)射器和增加信號QPushButtonQIntPushButton{...signals:voidclicked(int);...}{QIntPushButton*b;b=newQIntPushButton(1);connect(b,SIGNAL(clicked(int)),this,SLOT(keyPressed(int)));b=newQIntPushButton(2);connect(b,SIGNAL(clicked(int)),this,SLOT(keyPressed(int)));b=newQIntPushButton(3);connect(b,SIGNAL(clicked(int)),this,SLOT(keyPressed(int)));...}與值關聯?解決方法#2:子類發(fā)射器和增加信號QPushB解決方案評價#1:多個槽許多槽包含幾乎相同的代碼難于維護
(一個小的變化影響所有槽)難于擴展
(每次都要新建槽)#2:子類發(fā)射器和增加信號額外的專用類
(難于重用)難于擴展
(每個情況需新建子類)解決方案評價#1:多個槽信號映射器QSignalMapper
類解決了這個問題將每個值映射到每個發(fā)射器介于可重用類之間{QSignalMapper*m=QSignalMapper(this);QPushButton*b;b=newQPushButton("1");connect(b,SIGNAL(clicked()),m,SLOT(map()));m->setMapping(b,1);...connect(m,SIGNAL(mapped(int)),this,SLOT(keyPressed(int)));}創(chuàng)建一個信號映射器關聯按鈕到映射器關聯一個發(fā)射器和一個值。關聯映射器到槽上。信號映射器QSignalMapper類解決了這個問題{創(chuàng)建信號映射器QSignalMapper{...publicslots:voidkeyPressed();...}connectionsconnection信號映射器把每一個按鈕和值關聯起來。這些值都被映射。當一個值被映射,映射器發(fā)出攜帶關聯的值的映射信號(int)。信號映射器QSignalMapper{connections演講完畢,謝謝觀看!演講完畢,謝謝觀看!.Qt的對象模型和信號槽的概念QtinEducation.Qt的對象模型QtinEducationThisworkisaChinesetranslationoftheoriginalQtEducationalTrainingMaterialspublishedbyNokia:?2010NokiaCorporationanditsSubsidiary(-ies).Nokia,QtandtheNokiaandQtlogosaretheregisteredtrademarksofNokiaCorporationinFinlandandothercountriesworldwide.ThistranslationwascreatedbyCommunicationandComputerNetworkLaboratoryofGuangdongProvince,SouthChinaUniversityofTechnology.?2010CommunicationandComputerNetworkLaboratoryofGuangdongProvince,SouthChinaUniversityofTechnology.TheenclosedQtEducationalTrainingMaterialsareprovidedundertheCreativeCommonsAttribution-Non-Commercial-ShareAlike2.5LicenseAgreement.Thefulllicensetextisavailablehere:./licenses/by-nc-sa/2.5/legalcode.
此文檔內容是由諾基亞公司發(fā)布的原創(chuàng)Qt教育培訓文檔的中文翻譯:?2010諾基亞公司及其附屬公司。Nokia(諾基亞),Qt以及Nokia與Qt商標是Nokia公司在芬蘭和全球其他國家的注冊商標。
該翻譯版本由華南理工大學廣東省計算機網絡重點實驗室創(chuàng)造。?2010華南理工大學廣東省計算機網絡重點實驗室
本Qt教育培訓材料依照署名-非商業(yè)性使用-相同方式共享2.5許可協議(CreativeCommons
Attribution-Non-Commercial-ShareAlike2.5LicenseAgreement)發(fā)布。
完整的許可證文本可以在這里找到:./licenses/by-nc-sa/2.5/legalcode。
Qt的對象模型與信號槽的概念課件QObject類QObject是幾乎所有Qt類和所有部件(widget)的基類。它包含很多組成Qt的機制事件信號和槽屬性內存管理QObject類QObject是幾乎所有Qt類和所有部件(wQObject類QObject
是大部分Qt類的基類例外的例子是:類需要作為輕量級的類,例如圖元(graphicalprimitives)。數據容器(QString,QList,QChar等)需要可復制的類,因為QObject類是無法被復制的。QObject類QObject是大部分Qt類的基類QObject類它們可以擁有一個名字
(QObject::objectName)它們被放置在QObject實例的一個層次上它們可以有到其他
QObject
實例的聯接例子:在運行時復制一個部件有意義嗎?“QObject的實例是單獨的!”QObject類它們可以擁有一個名字(QObject::o元數據(Metadata)Qt用C++實現內省每一個
QObject
都有一個元對象元對象涉及:類名
(QObject::className)繼承
(QObject::inherits)屬性信號和槽普通信息(QObject::classInfo)元數據(Metadata)Qt用C++實現內省元數據元數據通過元對象編譯器(moc)在編譯時組合在一起。sources*.cppexecutablesobjectfiles*.oheaders*.h普通的C++生成過程includescompileslinks元數據元數據通過元對象編譯器(moc)在編譯時組合在一起。s元數據Metadata元數據通過元對象編譯器(moc)在編譯時組合在一起。moc從頭文件里面獲得數據。sources*.cppexecutablesobjectfiles*.oheaders*.hgeneratedmoc_*.cppQtC++生成過程includescompileslinkscompilesmocs元數據Metadata元數據通過元對象編譯器(moc)在編元數據moc找什么?classMyClass:publicQObject{
Q_OBJECTQ_CLASSINFO("author","JohnDoe")public:MyClass(constFoo&foo,QObject*parent=0);Foofoo()const;publicslots:voidsetFoo(constFoo&foo);signals:voidfooChanged(Foo);private:Foom_foo;};Qt關鍵字類的一般信息Q_OBJECT宏,
通常是第一步首先確認該類繼承自
Qobject(可能是間接)元數據moc找什么?classMyClass:pub內省(Introspection)類在運行時了解它們自己的信息對實現腳本和動態(tài)語言的綁定有很好的支持。if(object->inherits("QAbstractItemView")){QAbstractItemView*view=static_cast<QAbstractItemView*>(widget);view->...enumCapitalsEnum{Oslo,Helsinki,Stockholm,Copenhagen};intindex=object->metaObject()->indexOfEnumerator("CapitalsEnum");object->metaObject()->enumerator(index)->key(object->capital());能夠實現動態(tài)轉換而不需要運行時類型檢查(
RTTI)例子:它可以將枚舉值轉換成更容易閱讀和保存的字符串元對象了解細節(jié)內省(Introspection)類在運行時了解它們自己的信屬性(Properties)QObject有getter和setter函數屬性命名策略:color,setColor對于布爾:isEnabled,setEnabledclassQLabel:publicQFrame{Q_OBJECTQ_PROPERTY(QStringtextREADtextWRITEsetText)public:QStringtext()const;publicslots:voidsetText(constQString&);};Setter,返回空,將值當成唯一參數Getter,常量,返回值,沒有參數屬性(Properties)QObject有getter和s屬性為什么使用setter函數?可以驗證設置對可能的變化作出反應voidsetMin(intnewMin){if(newMin>m_max){qWarning("IgnoringsetMin(%d)asmin>max.",newMin);return;}...voidsetMin(intnewMin){...m_min=newMin;updateMinimum();}屬性為什么使用setter函數?voidsetMin(屬性Properties為什么使用getter函數?間接的屬性QSizesize()const{returnm_size;}intwidth()const{returnm_size.width();}屬性Properties為什么使用getter函數?QSi屬性Q_PROPERTY(typenameREADgetFunction[WRITEsetFunction][RESETresetFunction]
[NOTIFYnotifySignal][DESIGNABLEbool][SCRIPTABLEbool][STOREDbool][USERbool][CONSTANT][FINAL])屬性Q_PROPERTY(typename使用屬性直接獲取通過元信息和屬性系統在運行時發(fā)現屬性QStringtext=label->text();label->setText("HelloWorld!");QStringtext=object->property("text").toString();object->setProperty("text","HelloWorld");intQMetaObject::propertyCount();QMetaPropertyQMetaObject::property(i);QMetaProperty::name/isConstant/isDesignable/read/write/...使用屬性直接獲取QStringtext=label->動態(tài)屬性在運行時給對象增加屬性可以用來“標識”對象,等等。boolret=object->setProperty(name,value);QObject::dynamicPropertyNames()const真:如果屬性經過Q_PROPERTY定義
假:如果只是動態(tài)增加返回一個動態(tài)屬性的列表動態(tài)屬性在運行時給對象增加屬性boolret=obje創(chuàng)建自定義屬性classAngleObject:publicQObject{Q_OBJECTQ_PROPERTY(qrealangleREADangleWRITEsetAngle)public:AngleObject(qrealangle,QObject*parent=0);qrealangle()const;voidsetAngle(qreal);private:qrealm_angle;};宏,描述屬性初始化值GetterSetter私有狀態(tài)創(chuàng)建自定義屬性classAngleObject:pub
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025版安全設備安裝與銷售服務合同樣本
- 2025版第四章國際海洋工程技術合作合同
- 二零二五年度購房定金協議范本:毛坯房
- 二零二五年度節(jié)能環(huán)保型圍墻施工與能源管理系統合同
- 2025版電子元器件出口銷售合同模板與供應鏈管理技巧
- 二零二五年度工業(yè)制造廠房租賃居間代理合同范本
- 2025版購物中心娛樂項目租賃合同
- 二零二五年度公共建筑節(jié)能改造委托造價咨詢合同
- 2025至2030年中國浴室架行業(yè)市場發(fā)展現狀及投資戰(zhàn)略咨詢報告
- 2025版電子商務平臺服務合同標的交易風險控制指南
- 數據庫設計規(guī)范說明
- 美國專利法及實務培訓-上傳課件
- 新版中國電信員工手冊
- 2023年中國工商銀行軟件開發(fā)中心春季校園招聘500人筆試模擬試題及答案解析
- D500-D505 2016年合訂本防雷與接地圖集
- 中國重癥加強治療病房(ICU)建設與管理指南
- 社區(qū)矯正法課件
- 后勤保障樓幕墻施工方案新
- GB/T 19326-2022鍛制支管座
- GB/T 8949-2008聚氨酯干法人造革
- GB/T 30544.1-2014納米科技術語第1部分:核心術語
評論
0/150
提交評論