實現功能:
程式開始出現一個對話方塊,按下按鈕後便能進入主視窗,如果直接關閉這個對話方塊,便不能進入主視窗,整個程式也將退出。當進入主視窗後,我們按下按鈕,會彈出一個對話方塊,無論如何關閉這個對話方塊,都會回到主視窗。
實現原理:
程式裡我們先建立一個主工程,作為主介面,然後再建立一個對話方塊類,將其加入工程中,然後在程式中調用自己建立的對話方塊類來實現多視窗。
實現過程:
1.首先建立Qt4 Gui Application工程,工程名為nGui,Base class選為QWidget。建立好後工程檔案清單如。
2.建立對話方塊類,如,在建立中,選擇Qt Designer Form Class。
3.選擇Dialog without Buttons。
4.類名設為myDlg。
5.點擊Finish完成。注意這裡已經預設將其加入到了我們剛建的工程中了。
6.如,在mydlg.ui中拖入一個Push Button,將其上的文本改為“進入主視窗”,在其屬性視窗中將其objectName改為enterBtn,在下面的Signals and slots editor中進行訊號和槽的關聯,其中,Sender設為enterBtn,Signal設為clicked(),Receive設為myDlg,Slot設為accept()。這樣就實現了單擊這個按鈕使這個對話方塊關閉並發出Accepted訊號的功能。下面我們將利用這個訊號。
7.修改主函數main.cpp,如下:
#include <QtGui/QApplication>
#include “widget.h”
#include “mydlg.h” //加入標頭檔
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
myDlg my1; //建立自己建立的類的對象my1
if(my1.exec()==QDialog::Accepted) //利用Accepted訊號判斷enterBtn是否被按下
{
w.show(); //如果被按下,顯示主視窗
return a.exec(); //程式一直執行,直到主視窗關閉
}
else return 0; //如果沒被按下,則不會進入主視窗,整個程式結束運行
}
主函數必須這麼寫,才能完成所要的功能。
如果主函數寫成下面這樣:
#include <QtGui/QApplication>
#include “widget.h”
#include “mydlg.h”
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
myDlg my1;
if(my1.exec()==QDialog::Accepted)
{
Widget w;
w.show();
}
return a.exec();
}
這樣,因為w是在if語句裡定義的,所以當if語句執行完後它就無效了。這樣導致的後果就是,按下enterBtn後,主介面視窗一閃就沒了。如果此時對程式改動了,再次點擊運行時,就會出現error: collect2: ld returned 1 exit status的錯誤。這是因為雖然主視窗沒有顯示,但它只是隱藏了,程式並沒有結束,而是在後台運行。所以這時改動程式,再運行時便會出錯。你可以按下調試欄上面的紅色Stop停止按鈕來停止程式運行。你也可以在windows工作管理員的進程中將該進程結束,而後再次運行就沒問題了,當然先關閉Qt Creator,而後再重新開啟,這樣也能解決問題。
如果把程式改為這樣:
#include <QtGui/QApplication>
#include “widget.h”
#include “mydlg.h”
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
myDlg my1;
Widget w;
if(my1.exec()==QDialog::Accepted)
{
w.show();
}
return a.exec();
}
這樣雖然解決了上面主視窗一閃而過的問題,但是,如果在my1對話方塊出現的時候不點enterBtn,而是直接關閉對話方塊,那麼此時整個程式應該結束執行,但是事實是這樣的嗎?如果你此時對程式進行了改動,再次按下run按鈕,你會發現又出現了error: collect2: ld returned 1 exit status的錯誤,這說明程式並沒有結束,我們可以開啟windows工作管理員,可以看到我們的程式仍在執行。
因為return a.exec();一句表示只要主視窗介面不退出,那麼程式就會一直執行。所以只有用第一種方法,將該語句也放到if語句中,而在else語句中用else return 0; ,這樣如果enterBtn沒有被按下,那麼程式就會結束執行了。
到這裡,我們就實現了一個介面結束執行,然後彈出另一個介面的程式。下面我們在主視窗上加一個按鈕,按下該按鈕,彈出一個對話方塊,但這個對話方塊關閉,不會使主視窗關閉。
8.如,在主視窗加入按鈕,顯示文本為“彈出一個對話方塊”,在其上點擊滑鼠右鍵,在彈出的菜單中選擇go to slot。
9.我們選擇單擊事件clicked()。
10.我們在彈出的槽函數中添加一句:
my2.show();
my2為我們建立對話方塊類的另一個對象,但是my2我們還沒有定義,所以在widget.h檔案中添加相應代碼,如下,先加入標頭檔,再加入my2的定義語句,這裡我們將其放到private裡,因為一般的函數都放在public裡,而變數都放在private裡。
#ifndef WIDGET_H
#define WIDGET_H
#include <QtGui/QWidget>
#include “mydlg.h” //包含標頭檔
namespace Ui
{
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
private:
Ui::Widget *ui;
myDlg my2; //對my2進行定義
private slots:
void on_pushButton_clicked();
};
#endif // WIDGET_H
到這裡,再運行程式,便能完成我們實驗要求的功能了。整個程式裡,我們用兩種方法實現了訊號和槽函數的關聯,第一個按鈕我們直接在設計器中實現其關聯;第二個按鈕我們自己寫了槽函數語句,其實圖形的設計與直接寫代碼效果是一樣的。
這個程式裡我們實現了兩類視窗開啟的方式,一個是自身消失而後開啟另一個視窗,一個是開啟另一個視窗而自身不消失。可以看到他們實現的方法是不同的。