C/C++ Qt 自定義Dialog對話方塊元件應用

lyshark發表於2021-11-25

在上一篇博文 《C/C++ Qt 標準Dialog對話方塊元件應用》 中我給大家演示瞭如何使用Qt中內建的標準對話方塊元件實現基本的資料輸入功能。

但有時候我們需要一次性修改多個資料,使用預設的模態對話方塊似乎不太夠用,此時我們需要自己建立一個自定義對話方塊,這類對話方塊也是一種窗體,所以可以在其上面放置任何的通用元件,以實現更多複雜的開發需求。

目前自定義對話方塊與主窗體的通訊有兩種方式,一種是通過函式實現通訊,另一種則是通過訊號實現通訊,我們以通過函式通訊為基礎,解釋一下如何實現跨窗體通訊。

首先需要建立一個自定義對話方塊,對話方塊具體建立流程如下

  • 選擇專案 -> AddNew -> QT -> Qt設計師介面類 -> 選擇空白Dialog -> 命名為Dialog儲存

直接選中Dianlog.ui並繪製介面為以下,一個編輯框,兩個按鈕。

其次需要在Dialog對話方塊上增加兩個訊號,分別是點選關閉,並將訊號關聯到兩個槽函式上,其訊號應該寫成如下樣子。

接著我們點開dialog.cpp這個類則是對話方塊類,類內需要定義兩個成員函式,它們的功能如下:

  • 第一個 GetValue() 用來獲取當前編輯框內的資料並將資料返回給父窗體。
  • 第二個 SetValue() 用來接收傳入的引數,並將此引數設定到自身窗體中的編輯框內。
#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :QDialog(parent),ui(new Ui::Dialog)
{
    ui->setupUi(this);
}

// 用於MainWindow獲取編輯框中的資料
QString Dialog::GetValue()
{
    return ui->lineEdit->text();
}

// 用於設定當前編輯框中的資料為MainWindow
// https://www.cnblogs.com/lyshark
void Dialog::SetValue(QString x)
{
    ui->lineEdit->setText(x);
}

Dialog::~Dialog()
{
    delete ui;
}

void Dialog::on_BtnOk_clicked()
{

}
void Dialog::on_BtnCancel_clicked()
{

}

對於主函式來說,當使用者點選on_pushButton_clicked()按鈕時,我們需要動態將自己建立的Dialog載入,讀取出主窗體編輯框內的值並設定到子窗體內,當使用者按下QDialog::Accepted時則是獲取子窗體內的值,並將其設定到父窗體的編輯框內,主函式程式碼如下所示.

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "dialog.h"
#include <iostream>
#include <QDialog>

MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->lineEdit->setEnabled(false);
    ui->lineEdit->setText("hello lyshark");
}

MainWindow::~MainWindow()
{
    delete ui;
}

// By: LyShark
// https://www.cnblogs.com/lyshark
// 按鈕點選後執行
void MainWindow::on_pushButton_clicked()
{
    // 建立模態對話方塊
    Dialog *ptr = new Dialog(this);                                 // 建立一個對話方塊
    Qt::WindowFlags flags = ptr->windowFlags();                     // 需要獲取返回值
    ptr->setWindowFlags(flags | Qt::MSWindowsFixedSizeDialogHint);  // 設定對話方塊固定大小

    // 讀取MainWindows引數並設定到Dialog
    QString item = ui->lineEdit->text();
    ptr->SetValue(item);

    int ref = ptr->exec();             // 以模態方式顯示對話方塊
    if (ref==QDialog::Accepted)        // OK鍵被按下,對話方塊關閉
    {
        // 當BtnOk被按下時,則設定對話方塊中的資料
        QString the_value = ptr->GetValue();
        std::cout << "value = " << the_value.toStdString().data() << std::endl;
        ui->lineEdit->setText(the_value);
    }

    // 刪除釋放對話方塊控制程式碼
    delete ptr;
}

具體演示程式碼如下所示:


而對於訊號版來說,我們需要在dialog.h標頭檔案中增加sendText()訊號,以及on_pushButton_clicked()槽函式的宣告。

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = nullptr);
    ~Dialog();

// By: LyShark
// https://www.cnblogs.com/lyshark
private:
    Ui::Dialog *ui;


// 定義訊號(訊號只需宣告無需實現)
signals:
    void sendText(QString str);

private slots:
    void on_pushButton_clicked();
};

#endif // DIALOG_H

dialog.cpp中則在建構函式中建立連線,並提供一個傳送到MainWindow中的按鈕.

#include "dialog.h"
#include "ui_dialog.h"

// By: LyShark
// https://www.cnblogs.com/lyshark
Dialog::Dialog(QWidget *parent) :QDialog(parent),ui(new Ui::Dialog)
{
    ui->setupUi(this);
    connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(onBtnClick()));
}

Dialog::~Dialog()
{
    delete ui;
}

// 傳送訊號到MainWindow
void Dialog::on_pushButton_clicked()
{
    QString send_data = ui->lineEdit->text();
    emit sendText(send_data);
}

主窗體標頭檔案mainwindow.h中定義receiveMsg接受資料的槽函式.

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

// By: LyShark
// https://www.cnblogs.com/lyshark
private slots:
    // 定義槽函式
    void receiveMsg(QString str);
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

並在mainwindow.cpp中實現這個槽函式。

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "dialog.h"
#include <QDialog>

// By: LyShark
// https://www.cnblogs.com/lyshark
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->lineEdit->setEnabled(false);
}

// 接收訊號並設定到LineEdit上
void MainWindow::receiveMsg(QString str)
{
    ui->lineEdit->setText(str);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    Dialog *subwindow = new Dialog(this);
    // 當收到sendText訊號時使用receiveMsg槽函式處理
    connect(subwindow, SIGNAL(sendText(QString)), this, SLOT(receiveMsg(QString)));
    subwindow->show();
}

程式碼執行後與基於函式版的基本一致,但在靈活性上來說訊號版更好一些。

相關文章