初識Qt Object 類
本文介紹Qt Object 類,QObject把它們自己組織在對象樹中。當你創建一個QObject作為其它對象的父對象,這個對象會在父對象中自動調用insertChild()并且可以在父對象的children()列表中顯示出來。父對象擁有這個對象,比如,它將在它的析構函數中自動刪除它的孩子。你可以使用child()或者queryList()通過名稱和任意的類型來查找一個對象,并且使用objectTrees()來獲得樹根的列表。
QObject類介紹
QObject是Qt對象模型的中心。這個模型的中心特征就是一種用于無縫對象通訊的被叫做信號和槽的非常強大的機制。你能夠使用connect()把信號和槽連接起來并且可以用disconnect()來破壞這種連接。為了避免從不結束的通知循環,你可以調用blockSignals()臨時地阻塞信號。保護函數connectNotify()和disconnectNotify()使跟蹤連接成為可能。
QObject把它們自己組織在對象樹中。當你創建一個QObject作為其它對象的父對象,這個對象會在父對象中自動調用insertChild()并且可以在父對象的children()列表中顯示出來。父對象擁有這個對象,比如,它將在它的析構函數中自動刪除它的孩子。你可以使用child()或者queryList()通過名稱和任意的類型來查找一個對象,并且使用objectTrees()來獲得樹根的列表。
每個對象都有一個對象名稱(name()),能夠報告它的類名(className())并且它在QObject繼承層次中是否繼承了另一個類(inherits())。
當對象被刪除時,它發射destroyed()信號。你可以捕獲這個信號來避免對QObject的搖擺引用。QGuardedPtr類提供了一種文雅的方式來使用這個機制。
QObject可以通過event()接收事件并且過濾其它對象的事件。詳細情況請參考installEventFilter()和eventFilter()。一個方便的處理者,childEvent(),能夠被重新實現來捕獲子對象事件。
最后但不是最不重要的一點,QObject提供了Qt中最基本的定時器,關于定時器的高級支持請參考QTimer。
注意Q_OBJECT宏對于任何實現信號、槽和屬性的對象都是強制的。你也需要對源文件運行moc程序(元對象編譯器)。我們強烈建議在QObject的所有子類中使用這個宏,而不管它是不是實際使用了信號、槽和屬性,因為不這樣做也許會導致普通函數會出現為定義的問題。
所有的Qt窗口部件繼承了QObject。方便的函數isWidgetType()返回這個對象實際上是不是一個窗口部件。它比inherits( “QWidget” )快得多。
一些QObject函數,比如children()、objectTrees()和queryList()返回一個QObjectList。QObjectList是QObject的QPtrList。QObjectLists支持像QPtrLists同樣的操作并且又一個迭代器類QObjectListIt。也可以參考對象模型。
QObject 幾個重要的成員函數
1、排第一位的當然是信號的綁定connect
- bool QObject::connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * member )
[靜態]
把從sender對象發送的signal和receiver對象中的member連接起來,并且如果連接成功返回真,否則返回假。
你必須在說明signal和member的時候使用SIGNAL()和SLOT()兩個宏,例如:
- QLabel *label = new QLabel;
- QScrollBar *scroll = new QScrollBar;
- QObject::connect( scroll, SIGNAL(valueChanged(int)),
- label, SLOT(setNum(int)) );
這個實例確保了label總顯示當前滾動條的值。
一個信號也可以被連接到另一個信號上:
- class MyWidget : public QWidget
- {
- Q_OBJECT
- public:
- MyWidget();
- signals:
- void myUsefulSignal();
- private:
- QPushButton *aButton;
- };
- MyWidget::MyWidget()
- {
- aButton = new QPushButton( this );
- connect( aButton, SIGNAL(clicked()), SIGNAL(myUsefulSignal()) );
- }
在這個實例中,MyWidget的構造函數傳遞一個來自私有成員變量的信號,并且使它在MyWidget的一個相關名稱下可用。一個信號可以被連接到多個槽和信號上。多個信號可以被連接到一個槽上。如果一個信號被連接到幾個槽上,當信號被發射的時候,槽被激活的順序是任意的。如果信號和槽被成功連接,返回真。如果它不能創建連接,返回假,例如,如果QObject不能檢驗signal或member的存在,或者如果它們的標簽不協調。也可以參考disconnect()。
#p#
有涉及多線程的需要注意它的第5個參數:
enum Qt::ConnectionType
This enum describes the types of connection that can be used between signals and slots. In particular, it determines whether a particular signal is delivered to a slot immediately or queued for delivery at a later time.
With queued connections, the parameters must be of types that are known to Qt’s meta-object system, because Qt needs to copy the arguments to store them in an event behind the scenes. If you try to use a queued connection and get the error message:
2、和connect 成雙成對的disconnect
取消從sender對象發送的signal和對象receiver中的member的連接。
當這兩個有關對象中的一個被銷毀時,這個信號——槽連接就被移除了。
disconnect()通常被用在三種方式下,正如下面的例子所描述的。
1. 取消連接到一個對象的信號的任何事物:
- disconnect( myObject, 0, 0, 0 );
等于非靜態重載函數
- myObject->disconnect();
2. 取消連接到一個特定信號的任何事物:
- disconnect( myObject, SIGNAL(mySignal()), 0, 0 );
等于非靜態重載函數
- myObject->disconnect( SIGNAL(mySignal()) );
3. 取消一個特定接收者的所有連接:
- disconnect( myObject, 0, myReceiver, 0 );
等于非靜態重載函數
- myObject->disconnect( myReceiver );
0可以用做一個通配符,意義可能分別為“任何信號”、“任何接受對象”或者“一個接受對象中的任何槽”。
sender不能為0。(你不能在一個調用中取消來自多于一個對象的信號的連接。)
如果signal為0,它取消所有和這個對象的信號連接的receiver和member。如果不是,只由特定信號被取消聯接。
如果receiver為0,它取消連接到signal的任何事物。如果不是,只有receiver中的槽被取消連接。
如果member為0,它取消連接到receiver的任何事物。如果不是,只有名為member的槽被取消聯接并且其它所有槽被保留。如果receiver被省去,member必須為0,所以你不能取消所有對象中同一特定名稱槽的連接。
#p#
3、installEventFilter的使用
void QObject::installEventFilter ( const QObject * obj )
安裝事件過濾器obj到這個對象。
事件過濾器就是接收所有被發送到這個對象的事件的對象。這個過濾器可以停止事件或者把它再轉給這個對象。事件過濾器obj通過它的eventFilter()函數來接收事件。如果事件被過濾了(比如,停止了),eventFilter()函數必須返回真,否則它必須返回假。
如果有多個事件過濾器被安裝到同一個對象上,最后一個被安裝的事件過濾器將先被激活。
實例:
- #include <qwidget.h>
- class MyWidget : public QWidget
- {
- Q_OBJECT
- public:
- MyWidget( QWidget *parent = 0, const char *name = 0 );
- protected:
- bool eventFilter( QObject *, QEvent * );
- };
- MyWidget::MyWidget( QWidget *parent, const char *name )
- : QWidget( parent, name )
- {
- // 為父對象(如果有的話)安裝一個過濾器
- if ( parent )
- parent->installEventFilter( this );
- }
- bool MyWidget::eventFilter( QObject *o, QEvent *e )
- {
- if ( e->type() == QEvent::KeyPress ) {
- // 對于鍵被按下進行特殊處理
- QKeyEvent *k = (QKeyEvent *)e;
- qDebug( "Ate key press %d", k->key() );
- return TRUE; // 吃掉了這個事件
- } else {
- // 標準事件處理
- return QWidget::eventFilter( o, e );
- }
- }
例如,QAccel類使用這種技術來截取快捷鍵被按下。
警告:如果在你的eventFilter()函數中你刪除了接收對象,請確認返回真。否則,Qt會把這個事件轉給被刪除的對象并且程序也許會崩潰。
4、tr國際化使用
- QString QObject::tr ( const char * sourceText, const char * comment ) const
返回sourceText的翻譯版本,或者如果沒有合適的版本返回sourceText它自己。翻譯上下文是comment的QObject(默認為空)。所有使用Q_OBJECT宏的QObject對象有這個函數的重新實現,把子類名作為上下文。
小結:Qt Object 類介紹完了,并了解了QObject類是所有Qt對象的基類,QObject是Qt對象模型的中心。QObject也是很常用的一個大類希望本文對你有幫助,
【編輯推薦】