在上一篇博文 《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();
}
代碼運行后與基於函數版的基本一致,但在靈活性上來說信號版更好一些。
自定義對話框基本就這些內容,靈活運行這些組件,很容易就能實現一些有用的表格編輯器。