1. 程式人生 > >QT窗體間傳值總結

QT窗體間傳值總結

 在寫程式時,難免會碰到多窗體之間進行傳值的問題。依照自己的理解,我把多窗體傳值的可以使用的方法歸納如下:

      1.使用QT中的Signal&Slot機制進行傳值;

      2.使用全域性變數;

      3.使用public形式的函式介面;

      4.使用QT中的Event機制(這種沒有把握,但是感覺應該是可以的),但是實現起來應該比前幾種複雜,這裡不做討論。

       下面分別進行討論:

1.使用QT中的Signal&Slot機制進行傳值:

      QT中的Signal&Slot機制相比於MFC中的訊息機制簡單了許多,它保證了任何物件之間均可以通過這種方式進行通訊,甚至可以得到訊息的sender。這裡就拿一個簡單的窗體間傳值作為例子。

      首先看一下主窗體MainWindow:

      在設計器中拖拽一個Label和一個TextEdit控制元件到介面上,TextEdit用於顯示傳遞過來的資料。

    建立一個右下有兩個按鍵的對話方塊,放置一個Label和一個LineEdit。

     下面就是編碼的操作了,我們需要在Dialog中宣告一個訊號,當用戶點選OK時傳遞LineEdit中的內容到mainWindow中,具體的dialog.h程式碼為:

  1. #ifndef DIALOG_H
  2. #define DIALOG_H
  3. #include <QDialog>
  4. namespace Ui {  
  5. class Dialog;  
  6. }  
  7. class Dialog : public QDialog  
  8. {  
  9.     Q_OBJECT  
  10. public:  
  11.     explicit Dialog(QWidget *parent = 0);  
  12.     ~Dialog();  
  13. private:  
  14.     Ui::Dialog *ui;  
  15. signals:  
  16.     void  sendData(QString);  
  17. private slots:  
  18.     void on_buttonBox_accepted();  
  19. };  
  20. #endif // DIALOG_H 
      其中的signals:void sendData(QString)便是我們需要的訊號函式,同時聲明瞭一個槽函式

       void on_buttonBox_accepted();用於相應確定按鈕的click事件。下面就是需要在該函式中產生一個訊號。程式碼如下:

  1. void Dialog::on_buttonBox_accepted()  
  2. {  
  3.     emit sendData(ui->lineEdit->text());  
  4. }  
      程式碼異乎尋常的簡單,只需要用emit的方式呼叫sendData函式,將需要的引數傳遞進去即可。而MainWindow中則需要宣告接收的槽函式,注意槽函式引數只能與訊號函式少或相等,而不能多於訊號函式引數個數。在MainWindow的標頭檔案中宣告槽函式:
  1. private slots:  
  2.     void receiveData(QString data);  

    為了便於測試,我只在MainWindow的建構函式中建立了一個Dialog物件,並連線了訊號和槽,具體為:
  1. MainWindow::MainWindow(QWidget *parent) :  
  2.     QMainWindow(parent),  
  3.     ui(new Ui::MainWindow)  
  4. {  
  5.     ui->setupUi(this);  
  6.     //訊號槽方式下父子窗體傳值的測試
  7.     Dialog *dlg = new Dialog;  
  8.     //關聯訊號和槽函式
  9.     connect(dlg,SIGNAL(sendData(QString)),this,SLOT(receiveData(QString)));  
  10.    // dlg->setModal(true); 不論是模態或者非模態都可以正常傳值
  11.     dlg->show();  
  12. }  
      這裡,我沒有將父視窗的指標傳遞到Dialog中,如new Dialog(this),這種方式下,實際上可以歸結到第三類傳值方式中去。因為此時,可以使用MainWindow中的父視窗的函式進行資料的賦值和操作。

      這裡,可能還有一個問題就是,父視窗如何給子視窗傳值,一方面,仍然可以使用訊號和槽的方式進行,但是,我感覺更便利的方式倒是使用這種public介面的方式進行傳值。這種來的更直接和明顯。當然,可以看出Signal&Signal方式進行此類的處理會更有通用性。

    在receiveData(QString)的槽函式中進行接收到資料的處理,這裡僅僅進行了簡單的顯示:

  1. void MainWindow::receiveData(QString data)  
  2. {  
  3.     ui->textEdit->setText(data);  
  4. }  

    最後看下結果:

  

       最終的結果,因為訊號和槽可以是多對多的,所以,在類似多個窗體廣播資訊時,這種方式就很有用,當然也可以使用全域性變數的形式。

這裡介紹另一種方式全域性變數進行傳值,在上一次的介面中的mainWindow和dialog中分別加入一個Label和LineEdit以及一個pushbutton。效果如:


       執行方式為在主介面mainWindow中單擊全域性變數按鈕對全域性變數進行賦值,賦值完成後,在Dialog中單擊全域性變數在LineEdit中顯示全域性變數的值,可以發現這種方式下可以很容易的反轉傳遞內容。

        具體實現為:

       在mainWindow.cpp檔案中加入:

  1. QString globaldata;         //宣告一個全域性變數用於窗體間傳值
      在全域性傳值按鈕的clicked事件中對gloabaldata進行賦值:
  1. void MainWindow::on_globalpb_clicked()  
  2. {  
  3.     globaldata = ui->lineEdit->text();  
  4. }  
    在Dialog.cpp檔案中宣告外部變數:
  1. extern QString globaldata;  
    在全域性傳值按鈕的clicked事件中對gloabaldata進行顯示:
  1. void Dialog::on_pushButton_clicked()  
  2. {  
  3.     ui->lineEdit_2->setText(globaldata);  
  4. }  
         這種方式,可以看到一些缺點,就是不容易對UI介面進行實時顯示,但是這對於一個系統來講也有一些優勢,就是可以方便地將一個系統的配置分配到相關的UI介面中去,但是,同樣的,也增加了程式之間的耦合性。

      為了節省篇幅,這裡不將最後的結果上傳上來了, 下一博文,將介紹窗體間傳值的另一種方式:public函式介面方式。


這裡介紹另一種,使用public函式介面的方式,這裡就牽扯到兩個方向間的傳值,父到子以及子到父視窗,通過這種方式都很容易做到,如子到父,可以在子窗體中實現一個public方法如prepareDoingData(&data),將需要處理的data的引用傳遞到子窗體,子窗體中可以對其進行操作,這裡展示父到子的傳值:

          在Dialog介面中增加一個TextEdit用於顯示最終傳遞的內容,並增加一個公有的方法:

  1. public:  
  2.     void setTextEditData(QString data);  
  3. void Dialog::setTextEditData(QString data)  
  4. {  
  5.     ui->textEdit->setText(data);  
  6. }  

      上面部分是在標頭檔案中的內容,下面為在.cpp中的內容,而在mainwindow.cpp中只需要進行呼叫即可:
  1. dlg->setTextEditData(QString("我來測試公有介面方式傳值!"));  
最終的結果         至此,三種傳值的方式已經全部講解完畢,具體在專案中國使用哪種方式進行傳值,則要視具體情況而定。個人感覺,基本傳值可以採用訊號槽方式降低耦合,系統配置可以使用單例模式然後在各個介面中進行配置,而public介面方式則適用於父子間窗體傳值。