Qt界面編程:窗口傳值方式


1、問題

  一個這樣的場景:主窗口界面有一個菜單項,點擊該菜單項彈出一個對話框。點擊對話框上的測試按鈕,顯示主窗口類中的一個字符串成員的內容。這就是整個窗口傳值的需求描述。如何解決呢?首先想到的解決方法自然是使用Qt自帶的signal/slot機制。即首先發信號給父窗口,父窗口接到信號執行槽函數發送一個攜帶所需數據的信號給子窗口。但是疑問來了:要在子窗口中接收到父窗口的信號必須進行signal和slot的綁定。這需要主窗口類的定義(1)。擔心頭文件的遞歸包含,我們只好再想另外一個方法。直接在子窗口中利用指向父窗口的指針來訪問父窗口類的成員如何?但是,這顯然也牽涉到了頭文件的遞歸包含(2)。但,不試一試怎么知道?畢竟很多事情是無法用理論來解釋的。

2、嘗試解決

  • 使用環境:Qt5.0,  Qt creator2.6, Windows XP sp3 32bit
  • 創建一個主窗口類和子窗口類,在主窗口類中聲明一個QString類型的成員變量,訪問權限設置為public(3),並在構造函數中進行初始化
  • 在子窗口增加一個QLabel組件,用於顯示父窗口的成員變量的內容。
  • 在父類中調用子類彈出子窗口時,要給子窗口的構造函數傳遞this指針,以設置子窗口的父窗口。因為子窗口的構造函數帶一個默認值0,也即是沒有設置父窗口的。

3、代碼

 1 //主窗口的.h文件,頭文件和預處理機制已經去掉
 2 class MainWindow : public QMainWindow
 3 {
 4     Q_OBJECT
 5     
 6 public:
 7     explicit MainWindow(QWidget *parent = 0);
 8     ~MainWindow();
 9     
10 private slots:
11     void on_actionPopup_triggered();
12 
13 private:
14     Ui::MainWindow *ui;
15     QString name;    //declaration
16 };
17 //主窗口的cpp實現文件,其他同上
18 MainWindow::MainWindow(QWidget *parent) :
19     QMainWindow(parent),
20     ui(new Ui::MainWindow)
21 {
22     ui->setupUi(this);
23     name = "YES";   //initialization of member variable
24 }
25 
26 MainWindow::~MainWindow()
27 {
28     delete ui;
29 }
30 
31 void MainWindow::on_actionPopup_triggered()
32 {
33     Dialog myDlg(this);   //This is important
34     myDlg.exec();
35 }
36 //Dialog header
37 namespace Ui {
38 class Dialog;
39 }
40 
41 class Dialog : public QDialog
42 {
43     Q_OBJECT
44     
45 public:
46     explicit Dialog(QWidget *parent = 0);
47     ~Dialog();
48     
49 private slots:
50     void on_pushButton_test_clicked();
51 
52 private:
53     Ui::Dialog *ui;
54 };
55 //dialog implementation
56 Dialog::Dialog(QWidget *parent) :
57     QDialog(parent),
58     ui(new Ui::Dialog)
59 {
60     ui->setupUi(this);
61 }
62 
63 Dialog::~Dialog()
64 {
65     delete ui;
66 }
67 
68 void Dialog::on_pushButton_test_clicked()
69 {
70     MainWindow* ptr = (MainWindow*)parentWidget();  //conversion
71     ui->label->setText(ptr->name);
72 }

4、解釋
  注意上面的指針轉換,MainWindow* ptr = (MainWindow*)parentWidget();,這句話首先調用parentWidget()獲得子窗口的父窗口指針,其類型為QWidget類型,故此需要強制轉換為MainWindow類型。所以在子窗口的頭文件的中必須要包含主窗口的頭文件,否則連編譯都無法通過。其次是在父窗口中調用的方式:    DialogmyDlg(this); myDlg.exec();必須要傳遞this指針給子窗口的構造函數進行初始化。否則,parentWidget()將無法取得父窗口的指針。

5、新問題

  1. 頭文件包含問題(上面1,2所標示)。在父窗口的頭文件中,包含了子窗口的頭文件。這原本沒有問題。但是在子窗口中又再次包含了父窗口的頭文件,這一樣一來彼此包含,你中有我我中有你,生生不息了。為什么能這樣工作呢?是不是頭文件的預編譯機制突破了這一限制?
  2. 上面3所標識的問題,其實並沒有嚴格的要求,至少在Qt Creator中沒有這樣的限制。你可以將該成員變量設置為private,protected, public的,但是在子窗口中照樣能訪問。雖然按照C++的設計原則來說,數據應該是類的私有部分。這到底是為什么呢?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM