对话框分为多种,常见的有通用对话框,自定义对话框,模态对话框,非模态对话框等,其中通用对话框包括了,QFileDialog文件对话框,QColorDialog颜色对话框,QFontDialog字体对话框,QInputDialog输入对话框等,自定义对话框则主要是实现自己布局的简单页面,区别于窗体对话框则显得更加简单一些,除对话框外,多窗体设计也是最常用的,例如多窗体嵌入,MID窗体等,下面则是每种窗体的代码总结。
创建自定义窗体
1.首先使用两个控件,TableView主要是表格处理,TreeView主要是树形框,这两者可以通过 QItemSelectionModel 模型绑定起来从而可实现菜单联动。
# mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <iostream>
#include <QStandardItem>
#include <QItemSelectionModel>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QStandardItemModel *model; // 定义数据模型
QItemSelectionModel *selection; // 定义Item选择模型
};
#endif // MAINWINDOW_H
# mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
model = new QStandardItemModel(4,5,this);
selection = new QItemSelectionModel(model);
// 关联到tableView
ui->tableView->setModel(model);
ui->tableView->setSelectionModel(selection);
// 关联到treeView
ui->treeView->setModel(model);
ui->treeView->setSelectionModel(selection);
// 添加表头
QStringList HeaderList;
HeaderList << "序号" << "姓名" << "年龄" << "性别" << "婚否";
model->setHorizontalHeaderLabels(HeaderList);
// 批量添加数据
QStringList DataList[3];
QStandardItem *Item;
DataList[0] << "1001" << "admin" << "24" << "男" << "是";
DataList[1] << "1002" << "lyshark" << "23" << "男" << "否";
DataList[2] << "1003" << "lucy" << "37" << "女" << "是";
int Array_Length = DataList->length(); // 获取每个数组中元素数
int Array_Count = sizeof(DataList) / sizeof(DataList[0]); // 获取数组个数
for(int x=0; x<Array_Count; x++)
{
for(int y=0; y<Array_Length; y++)
{
Item = new QStandardItem(DataList[x][y]);
model->setItem(x,y,Item);
}
}
}
MainWindow::~MainWindow()
{
delete ui;
}
2.首先来创建一个自定义对话框,创建对话框先要在项目上右键,选项【addNew】选择【QT】点击【QT设计师】,我们这里选择最后一个最为界面框架。
3.默认情况下,QT会生成三个文件【.ui 界面库】【.h 头文件】【.cpp 源文件】名字相同的三个文件,对应一个界面。
4.设计好界面布局,然后开始写代码。
dialogsize.h
#ifndef DIALOGSIZE_H
#define DIALOGSIZE_H
#include <QDialog>
namespace Ui {
class DialogSize;
}
class DialogSize : public QDialog
{
Q_OBJECT
public:
explicit DialogSize(QWidget *parent = nullptr);
~DialogSize();
int rowCount(); // 获取对话框输入的行数
int columnCount(); // 获取对话框输入的列数
void etRowColumn(int row, int column); // 初始对话框上两个SpinBox的值
private:
Ui::DialogSize *ui;
};
#endif // DIALOGSIZE_H
dialogsize.cpp
#include "dialogsize.h"
#include "ui_dialogsize.h"
DialogSize::DialogSize(QWidget *parent) :QDialog(parent),ui(new Ui::DialogSize)
{
ui->setupUi(this);
}
DialogSize::~DialogSize()
{
delete ui;
}
// 主窗体调用获取当前行数
int DialogSize::rowCount()
{
return ui->spinBoxRow->value();
}
// 主窗体调用获取当前列数
int DialogSize::columnCount()
{
return ui->spinBoxColumn->value();
}
// 设置主窗体中的TableView行数与列数
void DialogSize::setRowColumn(int row, int column)
{
ui->spinBoxRow->setValue(row);
ui->spinBoxColumn->setValue(column);
}
mainwindow.cpp 主窗体中按钮一被点击时执行。
// 当按钮1被点击触发
void MainWindow::on_pushButton_clicked()
{
DialogSize *ptr = new DialogSize(this); // 创建一个对话框
Qt::WindowFlags flags = ptr->windowFlags(); // 需要获取返回值
ptr->setWindowFlags(flags | Qt::MSWindowsFixedSizeDialogHint); // 设置对话框固定大小
ptr->setRowColumn(model->rowCount(),model->columnCount()); // 对话框数据初始化
int ref = ptr->exec(); // 以模态方式显示对话框
if (ref==QDialog::Accepted) // OK键被按下,对话框关闭
{
// 当BtnOk被按下时,则设置对话框中的数据
int cols=ptr->columnCount();
model->setColumnCount(cols);
int rows=ptr->rowCount();
model->setRowCount(rows);
}
// 最后删除释放对话框句柄
delete ptr;
}
配置完后,我们还需要绑定两个槽函数,首先来到dialog窗体上,手动添加两条槽函数,当按钮被点击后,后发送一个信号,主窗体接收到后处理即可。
运行效果如下,这是一个模态对话框,所谓模态就是说,当打开时不能再次操作主窗体,只有模态对话框关闭时才能继续操作主窗体。
接着来写一个非模态对话框,这次创建一个Dialog名字就叫做DialogHead并绘制好界面。
dialoghead.h
#ifndef DIALOGHEAD_H
#define DIALOGHEAD_H
#include <QDialog>
#include <QStringListModel>
namespace Ui {
class DialogHead;
}
class DialogHead : public QDialog
{
Q_OBJECT
public:
explicit DialogHead(QWidget *parent = nullptr);
~DialogHead();
void setHeaderList(QStringList& headers); // 设置表头数据
QStringList headerList(); // 返回表头数据
private:
QStringListModel *model; // 定义数据模型
Ui::DialogHead *ui;
};
#endif // DIALOGHEAD_H
dialoghead.cpp
#include "dialoghead.h"
#include "ui_dialoghead.h"
DialogHead::DialogHead(QWidget *parent) :QDialog(parent),ui(new Ui::DialogHead)
{
ui->setupUi(this);
model = new QStringListModel;
ui->listView->setModel(model);
}
DialogHead::~DialogHead()
{
delete ui;
}
// 设置当前listView中的数据
void DialogHead::setHeaderList(QStringList &headers)
{
model->setStringList(headers);
}
// 返回当前的表头
QStringList DialogHead::headerList()
{
return model->stringList();
}
mainwindow.cpp
// 对话框设置表头数据
void MainWindow::on_pushButton_2_clicked()
{
DialogHead *ptr = new DialogHead(this);
Qt::WindowFlags flags = ptr->windowFlags();
ptr->setWindowFlags(flags | Qt::MSWindowsFixedSizeDialogHint);
// 如果表头列数变化,则从新初始化
if(ptr->headerList().count() != model->columnCount())
{
QStringList strList;
// 获取现有的表头标题
for (int i=0;i<model->columnCount();i++)
{
strList.append(model->headerData(i,Qt::Horizontal,Qt::DisplayRole).toString());
}
// 用于对话框初始化显示
ptr->setHeaderList(strList);
}
int ref = ptr->exec(); // 调用弹窗
if(ref==QDialog::Accepted)
{
QStringList strList=ptr->headerList();//获取对话框上修改后的StringList
model->setHorizontalHeaderLabels(strList);// 设置模型的表头标题
}
delete ptr;
}
最后在Dialog上绑定信号与曹。
前面的交互都是使用传统的相互引用实现的,实现起来较复杂,同样可以使用信号与曹来实现,将信号与曹关联起来,在进行操作时发送信号,槽函数接受并相应。
实现多窗体设计
多窗体分为窗体卡和MID窗体,这两种窗体也最常用。
1.首先是窗体卡片,这里在创建是应该选择Widget窗体,这个窗体最干净没啥控件,所以我们选择它。
formdoc.h
#ifndef FORMDOC_H
#define FORMDOC_H
#include <QWidget>
namespace Ui {
class FormDoc;
}
class FormDoc : public QWidget
{
Q_OBJECT
public:
explicit FormDoc(QWidget *parent = nullptr);
~FormDoc();
private:
Ui::FormDoc *ui;
};
#endif // FORMDOC_H
formdoc.cpp
#include "formdoc.h"
#include "ui_formdoc.h"
#include "mainwindow.h"
#include <QVBoxLayout>
#include <iostream>
FormDoc::FormDoc(QWidget *parent) :
QWidget(parent),
ui(new Ui::FormDoc)
{
ui->setupUi(this);
QVBoxLayout *Layout = new QVBoxLayout();
Layout->setContentsMargins(2,2,2,2);
Layout->setSpacing(2);
this->setLayout(Layout);
MainWindow *parWind = (MainWindow*)parentWidget(); //获取父窗口指针
QString ref = parWind->GetTableNumber(); // 获取选中标签索引
std::cout << ref.toStdString().data() << std::endl;
}
FormDoc::~FormDoc()
{
delete ui;
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "formdoc.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
QString GetTableNumber();
private slots:
void on_pushButton_clicked();
void on_tabWidget_tabCloseRequested(int index);
void on_tabWidget_currentChanged(int index);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <iostream>
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->tabWidget->setVisible(false);
ui->tabWidget->clear();//清除所有页面
ui->tabWidget->tabsClosable(); //Page有关闭按钮,可被关闭
}
MainWindow::~MainWindow()
{
delete ui;
}
// 定义函数来获取当前Table名字
QString MainWindow::GetTableNumber()
{
QString ref = QString(ui->tabWidget->currentIndex());
return ref;
}
void MainWindow::on_pushButton_clicked()
{
FormDoc *ptr = new FormDoc(this); // 新建选项卡
ptr->setAttribute(Qt::WA_DeleteOnClose); // 关闭时自动销毁
int cur = ui->tabWidget->addTab(ptr,QString::asprintf(" 192.168.1.%d",ui->tabWidget->count()));
ui->tabWidget->setTabIcon(cur,QIcon(":/image/1.ico"));
ui->tabWidget->setCurrentIndex(cur);
ui->tabWidget->setVisible(true);
}
// 关闭Tab时执行
void MainWindow::on_tabWidget_tabCloseRequested(int index)
{
if (index<0)
return;
QWidget* aForm=ui->tabWidget->widget(index);
aForm->close();
}
// 在无Tab页面是默认禁用
void MainWindow::on_tabWidget_currentChanged(int index)
{
Q_UNUSED(index);
bool en=ui->tabWidget->count()>0;
ui->tabWidget->setVisible(en);
}