天天看點

3、 QT基礎——第一個Qt小程式

3.1 按鈕的建立

在Qt程式中,最常用的控件之一就是按鈕了,首先我們來看下如何建立一個按鈕

QPushButton * btn = new QPushButton; 頭檔案 #include <QPushButton>

   //設定父親

   btn->setParent(this);

   //設定文字

   btn->setText("德瑪西亞");

   //移動位置

   btn->move(100,100);

   //第二種建立

   QPushButton * btn2 = new QPushButton("孫悟空",this);

   //重新指定視窗大小

   this->resize(600,400);

   //設定視窗标題

   this->setWindowTitle("第一個項目");

   //限制視窗大小

   this->setFixedSize(600,400);

上面代碼中,一個按鈕其實就是一個QPushButton類下的對象,如果隻是建立出對象,是無法顯示到視窗中的,是以我們需要依賴一個父視窗,也就是指定一個父親利用setParent函數即可,如果想設定按鈕上顯示的文字利用setText,移動按鈕位置用move

        對于視窗而言,我們可以修改左上角視窗的标題setWindowTitle,重新指定視窗大小:resize,或者設定固定的視窗大小setFixedSize;

3.2 對象模型(對象樹)

在Qt中建立對象的時候會提供一個Parent對象指針,下面來解釋這個parent到底是幹什麼的。

QObject是以對象樹的形式組織起來的。

當你建立一個QObject對象時,會看到QObject的構造函數接收一個QObject指針作為參數,這個參數就是 parent,也就是父對象指針。

這相當于,在建立QObject對象時,可以提供一個其父對象,我們建立的這個QObject對象會自動添加到其父對象的children()清單。

當父對象析構的時候,這個清單中的所有對象也會被析構。(注意,這裡的父對象并不是繼承意義上的父類!)

這種機制在 GUI 程式設計中相當有用。例如,一個按鈕有一個QShortcut(快捷鍵)對象作為其子對象。當我們删除按鈕的時候,這個快捷鍵理應被删除。這是合理的。

QWidget是能夠在螢幕上顯示的一切元件的父類。

QWidget繼承自QObject,是以也繼承了這種對象樹關系。一個孩子自動地成為父元件的一個子元件。是以,它會顯示在父元件的坐标系統中,被父元件的邊界剪裁。例如,當使用者關閉一個對話框的時候,應用程式将其删除,那麼,我們希望屬于這個對話框的按鈕、圖示等應該一起被删除。事實就是如此,因為這些都是對話框的子元件。

當然,我們也可以自己删除子對象,它們會自動從其父對象清單中删除。比如,當我們删除了一個工具欄時,其所在的主視窗會自動将該工具欄從其子對象清單中删除,并且自動調整螢幕顯示。

Qt 引入對象樹的概念,在一定程度上解決了記憶體問題。

當一個QObject對象在堆上建立的時候,Qt 會同時為其建立一個對象樹。不過,對象樹中對象的順序是沒有定義的。這意味着,銷毀這些對象的順序也是未定義的。

任何對象樹中的 QObject對象 delete 的時候,如果這個對象有 parent,則自動将其從 parent 的children()清單中删除;如果有孩子,則自動 delete 每一個孩子。Qt 保證沒有QObject會被 delete 兩次,這是由析構順序決定的。

如果QObject在棧上建立,Qt 保持同樣的行為。正常情況下,這也不會發生什麼問題。來看下下面的代碼片段:

{

   QWidget window;

   QPushButton quit("Quit", &window);

}

作為父元件的 window 和作為子元件的 quit 都是QObject的子類(事實上,它們都是QWidget的子類,而QWidget是QObject的子類)。這段代碼是正确的,quit 的析構函數不會被調用兩次,因為标準 C++要求,局部對象的析構順序應該按照其建立順序的相反過程。是以,這段代碼在超出作用域時,會先調用 quit 的析構函數,将其從父對象 window 的子對象清單中删除,然後才會再調用 window 的析構函數。

但是,如果我們使用下面的代碼:

   QPushButton quit("Quit");

   quit.setParent(&window);

情況又有所不同,析構順序就有了問題。我們看到,在上面的代碼中,作為父對象的 window 會首先被析構,因為它是最後一個建立的對象。在析構過程中,它會調用子對象清單中每一個對象的析構函數,也就是說, quit 此時就被析構了。然後,代碼繼續執行,在 window 析構之後,quit 也會被析構,因為 quit 也是一個局部變量,在超出作用域的時候當然也需要析構。但是,這時候已經是第二次調用 quit 的析構函數了,C++ 不允許調用兩次析構函數,是以,程式崩潰了。

由此我們看到,Qt 的對象樹機制雖然幫助我們在一定程度上解決了記憶體問題,但是也引入了一些值得注意的事情。這些細節在今後的開發過程中很可能時不時跳出來煩擾一下,是以,我們最好從開始就養成良好習慣,在 Qt 中,盡量在構造的時候就指定 parent 對象,并且大膽在堆上建立。

3.3 Qt視窗坐标體系

坐标體系:

以左上角為原點(0,0),X向右增加,Y向下增加。

3、 QT基礎——第一個Qt小程式

對于嵌套視窗,其坐标是相對于父視窗來說的。

繼續閱讀