Qt Object 類簡介--Qt 類簡介專題(二)

詳細描述

QObject類是所有Qt對象的基類。

QObjectQt對象模型的中心。這個模型的中心特徵就是一種用於無縫對象通訊的被叫做信號和槽的非常強大的機制。你能夠使用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 * signalconst QObject * receiver, constchar * 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()。

有涉及多線程的需要注意它的第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.

Constant Value Description
Qt::AutoConnection 0 (default) Same as DirectConnection, if the emitter and receiver are in the same thread. Same as QueuedConnection, if the emitter and receiver are in different threads.
Qt::DirectConnection 1 The slot is invoked immediately, when the signal is emitted.
Qt::QueuedConnection 2 The slot is invoked when control returns to the event loop of the receiver’s thread. The slot is executed in the receiver’s thread.
Qt::BlockingQueuedConnection 4 Same as QueuedConnection, except the current thread blocks until the slot returns. This connection type should only be used where the emitter and receiver are in different threads. Note: Violating this rule can cause your application to deadlock.
Qt::UniqueConnection 0x80 Same as AutoConnection, but the connection is made only if it does not duplicate an existing connection. i.e., if the same signal is already connected to the same slot for the same pair of objects, then the connection will fail. This connection type was introduced in Qt 4.6.
Qt::AutoCompatConnection 3 The default type when Qt 3 support is enabled. Same as AutoConnection but will also cause warnings to be output in certain situations. See Compatibility Signals and Slots for further information.

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,所以你不能取消所有對象中同一特定名稱槽的連接。

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 = 0const 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 *)
    {
        if ( e->type() == QEvent::KeyPress ) {
            // 對於鍵被按下進行特殊處理
            QKeyEvent *= (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對象有這個函數的重新實現,把子類名作爲上下文。

發佈了1 篇原創文章 · 獲贊 31 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章