主页 > 电脑硬件  > 

Qt学习(五)自定义对话框,多窗口开发---添加设计师类,MDI多窗口开发

Qt学习(五)自定义对话框,多窗口开发---添加设计师类,MDI多窗口开发
一 对话框 实现功能:打开文件,选择目录,保存文件,选择颜色,选择字体,输入信息, 消息提示框 #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: void on_pushButtonSelectOneFile_clicked(); void on_pushButtonSelectMultiFile_clicked(); void on_pushButtonSelectRoot_clicked(); void on_pushButtonSaveFile_clicked(); void on_pushButtonColor_clicked(); void on_pushButtonFont_clicked(); void on_pushButtonInputString_clicked(); void on_pushButtonInputInt_clicked(); void on_pushButtonInputFloat_clicked(); void on_pushButtonSelectItem_clicked(); void on_pushButtonQuestion_clicked(); void on_pushButtonMessage_clicked(); void on_pushButtonWarning_clicked(); void on_pushButtonWarningSerious_clicked(); void on_pushButtonVersion_clicked(); void on_pushButtonVersionQT_clicked(); void on_pushButton_clicked(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H #include "mainwindow.h" #include "ui_mainwindow.h" #include <QFileDialog> #include <QTextStream> #include <QColorDialog> #include <QFontDialog> #include <QInputDialog> #include <QMessageBox> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButtonSelectOneFile_clicked() { QString filename = QFileDialog::getOpenFileName(this, "选择一个文件", QDir::currentPath(), "文本文件(*txt);;C/C++文件(*.h *.c *.cpp);; 图片文件(*.jpg *.png *.gif);;所有文件(*.*)"); if(!filename.isEmpty()){ ui->plainTextEdit->appendPlainText(filename); } } void MainWindow::on_pushButtonSelectMultiFile_clicked() { QStringList filename = QFileDialog::getOpenFileNames(this, "选择多个文件", QDir::currentPath(), "文本文件(*txt);;C/C++文件(*.h *.c *.cpp);; 图片文件(*.jpg *.png *.gif);;所有文件(*.*)"); if(filename.count() > 0){ for(int i = 0; i < filename.count() ; i++) ui->plainTextEdit->appendPlainText(filename[i]); } } void MainWindow::on_pushButtonSelectRoot_clicked() { QString filename = QFileDialog::getExistingDirectory( this, "选择一个目录", QDir::currentPath(), QFileDialog::ShowDirsOnly); if(!filename.isEmpty()){ ui->plainTextEdit->appendPlainText(filename); } } void MainWindow::on_pushButtonSaveFile_clicked() { QString filename = QFileDialog::getSaveFileName(this, "保存文件", QDir::currentPath(), "文本文件(*txt);;C/C++文件(*.h *.c *.cpp);; 图片文件(*.jpg *.png *.gif);;所有文件(*.*)"); if(!filename.isEmpty()){ //把文本编辑器的内容保存到文本 QFile qfile(filename); if(! qfile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)){ return; } QTextStream stream(&qfile); stream << ui->plainTextEdit->toPlainText(); qfile.close(); ui->plainTextEdit->appendPlainText("已保存到:" + filename); } } void MainWindow::on_pushButtonColor_clicked() { QPalette pal = ui->plainTextEdit->palette(); //获取文本框的调色板 QColor textColor = pal.color(QPalette::Text); //获取文本框里面的本文的颜色 //调用颜色对话框 QColor color = QColorDialog::getColor( textColor, //初始颜色 this, //父窗口 "选择文本颜色"); //显示信息 if(color.isValid()){ pal.setColor(QPalette::Text,color); ui->plainTextEdit->setPalette(pal); } } void MainWindow::on_pushButtonFont_clicked() { QFont currentFont = ui->plainTextEdit->font(); bool ok = false; //调用字体选择对话框 QFont font = QFontDialog::getFont(&ok,currentFont); if(ok){ ui->plainTextEdit->setFont(font); } } void MainWindow::on_pushButtonInputString_clicked() { bool ok = false; //QLineEdit::Normal:一边输入一边显示 //QLineEdit::NoEcho 输入不显示,如密码 //QLineEdit::Password 密码输入方式,输入的时候显示掩码,离开显示星号 QString str = QInputDialog::getText( this, "输入文本对话框", "请输入姓名:", QLineEdit::Normal, "ROOK", //默认输入 &ok); //是否输入成功 if(ok && !str.isEmpty()){ ui->plainTextEdit->appendPlainText(str); } } void MainWindow::on_pushButtonInputInt_clicked() { bool ok = false; int value = QInputDialog::getInt( this, "输入整数对话框", "请输入字体大小:", ui->plainTextEdit->font().pointSize(), //默认输入 10, 80, //输入整数的最大最小值 1, &ok); //是否输入成功 if(ok){ QFont font = ui->plainTextEdit->font(); font.setPointSize(value); ui->plainTextEdit->setFont(font); } } void MainWindow::on_pushButtonInputFloat_clicked() { bool ok = false; double value = QInputDialog::getDouble( this, "输入浮点数对话框", "请输入一个浮点数:", 3.14, //默认输入 1.0, 100, //输入整数的最大最小值 2, //小数点后面位数 &ok); //是否输入成功 if(ok){ QString str = QString::asprintf("输入了以恶搞浮点数:%.2f",value); ui->plainTextEdit->appendPlainText(str); } } void MainWindow::on_pushButtonSelectItem_clicked() { bool ok = false; QStringList items = {"软件工程师","硬件工程师","测试工程师"}; QString str = QInputDialog::getItem( this, "列表选择对话框", "请选择岗位:", items, //有哪些可选项 1, //默认选项 true, //是否可编辑 &ok); if(ok && !str.isEmpty()){ ui->plainTextEdit->appendPlainText(str); } } void MainWindow::on_pushButtonQuestion_clicked() { QMessageBox::StandardButton ret = QMessageBox::question( this, "问题消息框", "内容已经修改,是否保存", //提示的内容 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::NoButton); //默认选项 if(ret == QMessageBox::Yes){ ui->plainTextEdit->appendPlainText("已选择: Yes"); }else if(ret == QMessageBox::No){ ui->plainTextEdit->appendPlainText("已选择: No"); }else if(ret == QMessageBox::Cancel){ ui->plainTextEdit->appendPlainText("已选择: 取消"); }else{ ui->plainTextEdit->appendPlainText("未选择"); } } void MainWindow::on_pushButtonMessage_clicked() { QMessageBox::information( this, "消息提示框", "文件已经保存!", //提示的内容 QMessageBox::Ok, QMessageBox::NoButton); //默认选项 } void MainWindow::on_pushButtonWarning_clicked() { QMessageBox::warning( this, "消息提示框", "文件被篡改!"); //默认选项 } void MainWindow::on_pushButtonWarningSerious_clicked() { QMessageBox::critical( this, "危机消息提示框", "系统即将重启!"); //默认选项 } void MainWindow::on_pushButtonVersion_clicked() { QMessageBox::about(this, "About消息提示框", "hahahha!"); //默认选项 } void MainWindow::on_pushButtonVersionQT_clicked() { QMessageBox::aboutQt(this, "aboutQt消息提示框"); //默认选项 } void MainWindow::on_pushButton_clicked() { ui->plainTextEdit->clear(); } 二 自定义对话框 使用类对象的对外的接口完成窗口之间的通讯

2.1 调整行列的自定义对话框 步骤:Add new->新建设计师类()->设计当前类的窗口样式->定义接口功能:单击调整行列按钮,弹出对话框,修改spinbox中对应的行列数,点击确定,对应表格中的行列会发生变化mainwindow.h 主函数调用的时候,需要包含该类的头文件#include "dialogresize.h",定义接口知识点:点击确定按钮,或者关闭按钮,如果不需要,实现的时候 accept()或者reject() / close()即可 private: Ui::MainWindow *ui; DialogResize *dialogResize; DialogHeader *dialogHeader; DialogLocation *dialogLocation;

“dialogresize.h”

#ifndef DIALOGRESIZE_H #define DIALOGRESIZE_H #include <QDialog> namespace Ui { class DialogResize; } class DialogResize : public QDialog { Q_OBJECT public: explicit DialogResize(QWidget *parent = nullptr); ~DialogResize(); int getRow(); int getCol(); private slots: void on_pushButtonok_clicked(); void on_pushButtonCancle_clicked(); private: Ui::DialogResize *ui; }; #endif // DIALOGRESIZE_H

“dialogresize.cpp”

#include "dialogresize.h" #include "ui_dialogresize.h" DialogResize::DialogResize(QWidget *parent) : QDialog(parent), ui(new Ui::DialogResize) { ui->setupUi(this); } DialogResize::~DialogResize() { delete ui; } int DialogResize::getRow() { return ui->spinBoxRow->value(); } int DialogResize::getCol() { return ui->spinBoxCol->value(); } void DialogResize::on_pushButtonok_clicked() { accept(); } void DialogResize::on_pushButtonCancle_clicked() { reject(); } 2.2 编辑表头按钮 功能:点击编辑表头按钮,对话框中会同步显示出已有的表头信息,如果在对话框中编辑表头,点击确定,那么对话框将关闭,对应的表的表头也将发生变化知识点1:在当前的设计师类中,新建了一个QStringListModel,因为对话框里面使用了listview知识点2: QStringListModel模型获取listview中的字符串,用语句 model->stringList();,设置listview中的字符串,用语句model->setStringList(list); #ifndef DIALOGEDITHEAD_H #define DIALOGEDITHEAD_H #include <QDialog> #include <QStringListModel> namespace Ui { class DialogEditHead; } class DialogEditHead : public QDialog { Q_OBJECT public: explicit DialogEditHead(QWidget *parent = nullptr); ~DialogEditHead(); void setHeadList(const QStringList& list); QStringList getHeaderList(); private slots: void on_pushButtonOk_clicked(); void on_pushButtonOk_2_clicked(); private: Ui::DialogEditHead *ui; QStringListModel *model; }; #endif // DIALOGEDITHEAD_H #include "dialogedithead.h" #include "ui_dialogedithead.h" DialogEditHead::DialogEditHead(QWidget *parent) : QDialog(parent), ui(new Ui::DialogEditHead) { ui->setupUi(this); model = new QStringListModel; ui->listView->setModel(model); } DialogEditHead::~DialogEditHead() { delete ui; } void DialogEditHead::setHeadList(const QStringList &list) { model->setStringList(list); } void DialogEditHead::on_pushButtonOk_clicked() { accept(); } void DialogEditHead::on_pushButtonOk_2_clicked() { reject(); } QStringList DialogEditHead::getHeaderList() { return model->stringList(); } 2.3 定位按钮 功能:点击定位单元格,弹出对话框,会显示当前单元格对应的位置,在对话框中输入文本,点击确定,文本会更新在相应的单元格里面知识点1:一般情况,按钮单击之后,会变成灰色 void showEvent(QShowEvent *event);,不会再变成原有的黑色,如果希望实现对话框关闭时,相应的按钮恢复成黑色,也就是恢复成可点击状态,添加函数void closeEvent(QCloseEvent *);知识点2:通过对话框,更新主窗口的内容,需要定义主窗口的接口,同时在mainwindow函数中自定义相应的接口,setCellText就是在mainwindow函数中自定义的公共函数接口 MainWindow *mainwindow = (MainWindow*)parentWidget(); mainwindow->setCellText(ui->spinBoxRow->value(), ui->spinBoxCol->value(), ui->plainTextEdit->toPlainText());

#ifndef DIALOGLOCATION_H #define DIALOGLOCATION_H #include <QDialog> namespace Ui { class DialogLocation; } class DialogLocation : public QDialog { Q_OBJECT public: explicit DialogLocation(QWidget *parent = nullptr); ~DialogLocation(); void setCurrentColRow(int row, int col); void setRowColMax(int maxRow, int maxCol); private slots: void on_pushButton_clicked(); void on_pushButton_2_clicked(); private: Ui::DialogLocation *ui; //窗口关闭的时候调用这个函数 void closeEvent(QCloseEvent *event); void showEvent(QShowEvent *event); }; #endif // DIALOGLOCATION_H #include "dialoglocation.h" #include "ui_dialoglocation.h" #include "mainwindow.h" DialogLocation::DialogLocation(QWidget *parent) : QDialog(parent), ui(new Ui::DialogLocation) { ui->setupUi(this); } DialogLocation::~DialogLocation() { delete ui; } void DialogLocation::setCurrentColRow(int row, int col) { ui->spinBoxCol->setValue(col); ui->spinBoxRow->setValue(row); } void DialogLocation::setRowColMax(int maxRow, int maxCol) { ui->spinBoxRow->setMaximum(maxRow-1); ui->spinBoxCol->setMaximum(maxCol-1); } void DialogLocation::showEvent(QShowEvent *event){ //把主窗口的定位组件再次设置为可以点击 MainWindow *mainwindow = (MainWindow*)parentWidget(); mainwindow->setActionLocationEnable(false); } void DialogLocation::closeEvent(QCloseEvent * ) { //把主窗口的定位组件再次设置为可以点击 MainWindow *mainwindow = (MainWindow*)parentWidget(); mainwindow->setActionLocationEnable(true); } void DialogLocation::on_pushButton_clicked() { //将指定位置的表格的内容设置为plaintext中的内容 MainWindow *mainwindow = (MainWindow*)parentWidget(); mainwindow->setCellText(ui->spinBoxRow->value(), ui->spinBoxCol->value(), ui->plainTextEdit->toPlainText()); //列自增和行自增的框的相应实现 if(ui->checkBoxRow->isChecked()){ ui->spinBoxRow->setValue(ui->spinBoxRow->value() + 1); } if(ui->checkBoxCol->isChecked()){ ui->spinBoxCol->setValue(ui->spinBoxCol->value() + 1); } } void DialogLocation::on_pushButton_2_clicked() { //reject(); //不会真正关闭对话框,不触发closeEvent,导致关闭对话框之后,标题栏的按钮没有恢复可点击状态 close(); } 2.4 MainWindow函数 2.4.1 知识点1:新建对话框的方式有3种, DialogResize *dialogresize = new DialogResize(this); 。。。。 //删除对话框 delete dialogresize; dialogLocation = new DialogLocation(this); if(dialogHead == NULL){ //只创建一次,可以重复使用 dialogHead = new DialogEditHead(this); //这种调用方式,不需要delete,this是父节点,关闭的时候会同时关闭子节点 } 2.4.2 知识点2:模态显示2种,一种是打开当前操作,其余地方不允许操作;另一种是其他地方允许操作

其它地方不允许操作

//把自定义的对话框显示出来 int ret = dialogresize->exec(); //模态显示,当前对话框工作,其他地方不允许操作 if(ret == QDialog::Accepted){ //点击了确定按钮 ,。。。。 }

其它地方允许操作

dialogLocation->show(); //以非模态方式显示 2.4.3 知识点3:获取tabelview模型种当前单元格的行列 QModelIndex index = selectionModel->currentIndex(); index.row(), index.column() 2.4.4 获取表头信息 QStringList list; for(int i =0; i < model->columnCount(); i++){ list.append(model->headerData(i,Qt::Horizontal).toString()); }

函数实现

#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QStandardItemModel> #include <QItemSelectionModel> #include "dialogedithead.h" #include "dialoglocation.h" QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); void setActionLocationEnable(bool enable); void setCellText(int row, int col, QString text); private slots: void on_actionResize_triggered(); void on_actionEditHead_triggered(); void on_actionLocation_triggered(); private: Ui::MainWindow *ui; QStandardItemModel *model; QItemSelectionModel *selectionModel; DialogEditHead *dialogHead = NULL; DialogLocation *dialogLocation = NULL; }; #endif // MAINWINDOW_H #include "mainwindow.h" #include "ui_mainwindow.h" #include "dialogresize.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); setCentralWidget(ui->tableView); model = new QStandardItemModel(10,6,this); selectionModel = new QItemSelectionModel(model); ui->tableView->setModel(model); ui->tableView->setSelectionModel(selectionModel); } MainWindow::~MainWindow() { delete ui; } void MainWindow::setActionLocationEnable(bool enable) { ui->actionLocation->setEnabled(enable); } void MainWindow::setCellText(int row, int col, QString text) { //清除原来的选择项 selectionModel->clearSelection(); selectionModel->setCurrentIndex(model->index(row,col),QItemSelectionModel::Select); model->setData(model->index(row,col),text); } void MainWindow::on_actionResize_triggered() { DialogResize *dialogresize = new DialogResize(this); //固定对话框大小,不允许拉伸 dialogresize->setWindowFlags( dialogresize->windowFlags() | Qt::MSWindowsFixedSizeDialogHint); //获取模型的当前的行列数,设置到自定义对话框,作为默认值显示 dialogresize->setRowCount(model->rowCount()); dialogresize->setColCount(model->columnCount()); //把自定义的对话框显示出来 int ret = dialogresize->exec(); //模态显示,当前对话框工作,其他地方不允许操作 if(ret == QDialog::Accepted){ //点击了确定按钮 int rows = dialogresize->rowCount(); int cols = dialogresize->colCount(); //改变tabelview的大小 model->setRowCount(rows); model->setColumnCount(cols); } //删除对话框 delete dialogresize; } void MainWindow::on_actionEditHead_triggered() { if(dialogHead == NULL){ //只创建一次,可以重复使用 dialogHead = new DialogEditHead(this); //这种调用方式,不需要delete,this是父节点,关闭的时候会同时关闭子节点 } //将tabelview的表头都传递给这个对话框 QStringList list; for(int i =0; i < model->columnCount(); i++){ list.append(model->headerData(i,Qt::Horizontal).toString()); } dialogHead->setHeadList(list); int ret = dialogHead->exec(); if(ret == QDialog::Accepted){ QStringList list = dialogHead->getHeaderList(); model->setHorizontalHeaderLabels(list); } } void MainWindow::on_actionLocation_triggered() { ui->actionLocation->setEnabled(false); //一次只允许创建一个窗口 //不同的新建方式 dialogLocation = new DialogLocation(this); //设置窗口样式 显示在最顶层,这样不会被其他窗口覆盖 dialogLocation->setWindowFlags(dialogLocation->windowFlags() | Qt::WindowStaysOnTopHint); //传递数据 dialogLocation->setRowColMax(model->rowCount(),model->columnCount()); QModelIndex index = selectionModel->currentIndex(); if(index.isValid()){ dialogLocation->setCurrentColRow(index.row(), index.column()); } dialogLocation->show(); //以非模态方式显示 } 三 自定义对话框 使用信号槽完成窗口之间的通讯

补充

知识点:两个窗口之间的通讯,需要定义信号和槽函数,信号一般定义在发送信号的窗口里面,槽函数一般定义在接收信号的窗口里面,在二案例的例子的基础上,对DialogLocation类进行修改,将类对象接口的通讯方式修改为信号与槽之间的通讯步骤1:点击对话框的确定按钮,要发送信号;单击定位单元格按钮之后,要求图标变成灰色,关闭单元格之后,要求突变恢复黑色,因此当前操作需要发送两个信号,在DialogLocation类中添加信号,信号不需要做实现 //信号定义在信号发送者 signals: void setCellText(int row, int col, QString &text); void setActionEnable(bool enable); 步骤2:在mainwindow.h中添加信号槽,重点:由于是不同窗口之间的信号传递,接口需要定义成public类型的 //槽函数定义在信号的接收者,因为是其它窗口信号和当前窗口的槽函数关联 public slots: void setCellText2(int row, int col, QString &text); void setActionEnable2(bool enable); 步骤3:槽函数的实现,在对应的按键,也即控制对话框弹出的按钮里面进行信号的关联,在之前的代码上没有任何改动,只是对信号进行了连接 void MainWindow::on_actionLocation_triggered() { ui->actionLocation->setEnabled(false); //一次只允许创建一个窗口 //不同的新建方式 dialogLocation = new DialogLocation(this); //设置窗口样式 显示在最顶层,这样不会被其他窗口覆盖 dialogLocation->setWindowFlags(dialogLocation->windowFlags() | Qt::WindowStaysOnTopHint); //传递数据 dialogLocation->setRowColMax(model->rowCount(),model->columnCount()); QModelIndex index = selectionModel->currentIndex(); if(index.isValid()){ dialogLocation->setCurrentColRow(index.row(), index.column()); } //关联 connect(dialogLocation, SIGNAL(setCellText(int, int ,QString &)), this,SLOT(setCellText2(int, int ,QString &))); connect(dialogLocation, SIGNAL(setActionEnable(bool)), this,SLOT(setActionEnable2(bool))); dialogLocation->show(); //以非模态方式显示 } 步骤4:在自定义窗口类中,发送信号 void DialogLocation::closeEvent(QCloseEvent * event) { //把主窗口的定位组件再次设置为可以点击 // MainWindow *mainwindow = (MainWindow*)parentWidget(); // mainwindow->setActionLocationEnable(true); emit setActionEnable(true); } void DialogLocation::showEvent(QShowEvent *event){ //把主窗口的定位组件再次设置为可以点击 // MainWindow *mainwindow = (MainWindow*)parentWidget(); // mainwindow->setActionLocationEnable(false); emit setActionEnable(false); } void DialogLocation::on_pushButton_clicked() { // //将指定位置的表格的内容设置为plaintext中的内容 // MainWindow *mainwindow = (MainWindow*)parentWidget(); // mainwindow->setCellText(ui->spinBoxRow->value(), // ui->spinBoxCol->value(), // ui->plainTextEdit->toPlainText()); QString text = ui->plainTextEdit->toPlainText(); emit setCellText(ui->spinBoxRow->value(), ui->spinBoxCol->value(), text); //列自增和行自增的框的相应实现 if(ui->checkBoxRow->isChecked()){ ui->spinBoxRow->setValue(ui->spinBoxRow->value() + 1); } if(ui->checkBoxCol->isChecked()){ ui->spinBoxCol->setValue(ui->spinBoxCol->value() + 1); } } 四 多窗口开发 —类似WPS的同时可以打开多个窗口 Qt主要窗口类 4.1 案例实现功能

formedit.h #ifndef FORMEDIT_H #define FORMEDIT_H #include <QWidget> namespace Ui { class FormEdit; } class FormEdit : public QWidget { Q_OBJECT public: explicit FormEdit(QWidget *parent = nullptr); ~FormEdit(); private: Ui::FormEdit *ui; }; #endif // FORMEDIT_H formedit.cpp #include "formedit.h" #include "ui_formedit.h" #include <QToolBar> #include <QVBoxLayout> FormEdit::FormEdit(QWidget *parent) : QWidget(parent), ui(new Ui::FormEdit) { ui->setupUi(this); //设计器里面没有toolbox,手动创建 QToolBar *bar = new QToolBar(this); bar->addAction(ui->actionOpen); bar->addSeparator(); bar->addAction(ui->actionFont); bar->addAction(ui->actionCut); bar->addAction(ui->actionCopy); bar->addAction(ui->actionPsate); bar->addAction(ui->actionCancle); bar->addAction(ui->actionRepeat); bar->addSeparator(); bar->addAction(ui->actionClose); bar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); //代码布局 plaintextEdit ,不能手动布局,否则手动添加的按钮没有位置了 QVBoxLayout *layout = new QVBoxLayout(); layout->addWidget(bar); layout->addWidget(ui->plainTextEdit); this->setLayout(layout); } FormEdit::~FormEdit() { delete ui; } mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: //void tabCloseRequested(int index); void on_tabWidget_tabCloseRequested(int index); void on_action_insideWidget_triggered(); void on_action_widget_triggered(); void on_action_insisdeMainwindow_triggered(); void on_action_mainwindow_triggered(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include "formedit.h" #include "mainwindow2.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); ui->tabWidget->clear(); //清除tabWidget中的默认选项 //让tab子窗口可关闭,有关闭按钮,但不会自动关闭,点击按钮会发送信号,需要自定义槽函数 ui->tabWidget->setTabsClosable(true); //设置主窗口的默认状态是最大化 this->setWindowState(Qt::WindowMaximized); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_tabWidget_tabCloseRequested(int index) { //获取对应的窗口 QWidget *widget = ui->tabWidget->widget(index); widget->close(); } void MainWindow::on_action_insideWidget_triggered() { FormEdit *form = new FormEdit(this); form->setAttribute(Qt::WA_DeleteOnClose); //设置窗体关闭时,自动销毁资源 //将当前的表插入tabWidget,index是对应窗口的序号 int index = ui->tabWidget->addTab(form,QString::asprintf("窗口%d",ui->tabWidget->count()+1)); ui->tabWidget->setCurrentIndex(index); } void MainWindow::on_action_widget_triggered() { FormEdit *form = new FormEdit(this); form->setAttribute(Qt::WA_DeleteOnClose); //设置窗体关闭时,自动销毁资源 form->setWindowTitle("基于widget的独立窗口"); form->setWindowFlag(Qt::Window, true); //这一行必须加,否则显示的独立窗口没有边框 form->show(); } void MainWindow::on_action_insisdeMainwindow_triggered() { MainWindow2 *window = new MainWindow2(this); window->setAttribute(Qt::WA_DeleteOnClose); int index = ui->tabWidget->addTab(window,QString::asprintf("窗口%d",ui->tabWidget->count()+1)); ui->tabWidget->setCurrentIndex(index); } void MainWindow::on_action_mainwindow_triggered() { MainWindow2 *window = new MainWindow2(this); window->setAttribute(Qt::WA_DeleteOnClose); //设置窗体关闭时,自动销毁资源 window->setWindowTitle("基于MainWindow2的独立窗口"); window->setWindowFlag(Qt::Window, true); //这一行必须加,否则显示的独立窗口没有边框 window->show(); } 其余文件代码见案例三,没有改动 4.2 案例4.1知识点总结 4.2.1 案例4.1的代码,是创建新的项目,完成formedit.h函数及其实现之后,直接将案例三中的代码合成添加到当前案例,在此合成过程中,两个案例中都有mainwindow同名函数,因此案例三中的该函数需要修改名字 直接将案例三中涉及mainwindow的位置都修改成mainwindow2或Mainwindow2,声明#ifndef MAINWINDOW2_H , #define MAINWINDOW2_H,头文件#include "mainwindow2.h"都要进行相应的修改另外,mainwindow2.ui文件也要进行修改,选中该文件->在explorer中显示->找到mainwindow2.ui->用记事本打开->修改如下对应位置,注意此处不是所有的都改,只改一个地方 选中项目文件名untitled27->添加现有文件->将案例三中的.cpp文件,.ui 文件,以及.h文件,案例三共有12个文件,导入当前项目即可,在案例四中调用案例三中的项目,直接通过MainWindow2 *window = new MainWindow2(this);创建街接口,就可以显示 4.2.2 Tab Widget的子窗口里面默认是没有关闭按钮的,需要手动建立信号槽来是实现 步骤1:在mainwindow.cpp文件中的构造函数里面,添加 ui->tabWidget->setTabsClosable(true); MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); ui->tabWidget->clear(); //清除tabWidget中的默认选项 //让tab子窗口可关闭,有关闭按钮,但不会自动关闭,点击按钮会发送信号,需要自定义槽函数 ui->tabWidget->setTabsClosable(true); //设置主窗口的默认状态是最大化 this->setWindowState(Qt::WindowMaximized); } 步骤2:在mainwindow.h文件, 自定义信号槽 void on_tabWidget_tabCloseRequested(int index);步骤3:实现槽函数 void MainWindow::on_tabWidget_tabCloseRequested(int index) { //获取对应的窗口 QWidget *widget = ui->tabWidget->widget(index); widget->close(); }

4.2.3 formedit.h是头通过新建设计师类,选择Widget来实现的,和Dialog without Buttons(案例三中使用的)不同,前者无法添加toolbox来手动拖动action,后者可以,所以当前案例的做法是,还是手动创建action以及plain text eidt,但是是在formedit.cpp中来布局和添加,不能手动布局

五 MDI开发案例 多窗口

组件名称 5.1 知识点总结 当前项目步骤: (1)创建一个设计师类,选择widget,对应文件名字formdoc,在对应的ui设计界面,只添加plain text edit 组件 (2)对于mianwindow类,在ui界面添加一个MDI area组件,然后手动添加toolbox对应的action知识点1:mianwindow里面的组件,实际的操作对象是formdoc里面的plain text edit 组件,所以对应的复制粘贴等选项,需要formdoc提供对外的接口,使得点击mianwindow里面的组件时能完成对文本的相关操作知识点2:MDI模式不需要手动为弹出的对话框添加取消按钮,也即每个框右上角的× 5.2 MDI模式

MDI效果图 非MDI效果图

5.3 展开模式

5.4 平铺模式

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(); bool fileOpen(); void loadFile(const QString &filename); void cut(); void paste(); void copy(); void setFont(); private: Ui::FormDoc *ui; bool m_fileOpen = false; }; #endif // FORMDOC_H formdoc.cpp #include "formdoc.h" #include "ui_formdoc.h" #include <QFile> #include <QTextStream> #include <QFileInfo> #include <QFontDialog> FormDoc::FormDoc(QWidget *parent) : QWidget(parent), ui(new Ui::FormDoc) { ui->setupUi(this); this->setAttribute(Qt::WA_DeleteOnClose); //窗口关闭消除资源 } FormDoc::~FormDoc() { delete ui; } bool FormDoc::fileOpen() { return m_fileOpen; } void FormDoc::loadFile(const QString &filename) { QFile file(filename); if(file.open(QIODevice::ReadOnly | QIODevice::Text)){ QTextStream stream(&file); ui->plainTextEdit->clear(); ui->plainTextEdit->setPlainText(stream.readAll()); file.close(); m_fileOpen = true; //把文件名作为窗口标题 filename是文件路径 QFileInfo info(filename); QString name = info.fileName(); this->setWindowTitle(name); } } void FormDoc::cut(){ ui->plainTextEdit->cut(); } void FormDoc::paste() { ui->plainTextEdit->paste(); } void FormDoc::copy() { ui->plainTextEdit->copy(); } void FormDoc::setFont() { QFont font = ui->plainTextEdit->font(); //获取当前字体 bool ok; font = QFontDialog:: getFont(&ok, font); ui->plainTextEdit->setFont(font); } mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: void on_actionNew_triggered(); void on_actionOpen_triggered(); void on_actionCloseALL_triggered(); void on_actionCopy_triggered(); void on_actionCut_triggered(); void on_actionFont_triggered(); void on_actionPaste_triggered(); void on_actionMDI_toggled(bool arg1); void on_actionExpand_triggered(); void on_actionPing_triggered(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include "formdoc.h" #include <QMdiSubWindow> #include <QFileDialog> #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } //新建文档 void MainWindow::on_actionNew_triggered() { FormDoc *form = new FormDoc(this); //把新建的床口添加到MDI ui->mdiArea->addSubWindow(form); //把当前新的文档编辑窗口,以独立的窗口显示 form->show(); } void MainWindow::on_actionOpen_triggered() { //如果当前MDI没有任何子窗口,open直接创建新的子窗口 //MDI当前已经有子窗口,就创新新的窗口 bool newNewForm = false; FormDoc *form = NULL; if(ui->mdiArea->subWindowList().count() == 0){ newNewForm = true; }else { //去除当前激活的窗口 form = (FormDoc*)ui->mdiArea->activeSubWindow()->widget(); if(form->fileOpen()){ newNewForm = true; } } //打开文件对话框 QString filename = QFileDialog::getOpenFileName(this, "打开一个文件", QDir::currentPath(), "源文件(*.h *.cpp);;文本文件(*.txt);;所有文件(*.*)"); if(filename.isEmpty()) { return; } if(newNewForm){ FormDoc *form2 = new FormDoc(this); ui->mdiArea->addSubWindow(form2); form2->show(); form2->loadFile(filename); } } void MainWindow::on_actionCloseALL_triggered() { ui->mdiArea->closeAllSubWindows(); } void MainWindow::on_actionCopy_triggered() { FormDoc *form = (FormDoc*)ui->mdiArea->activeSubWindow()->widget(); form->copy(); } void MainWindow::on_actionCut_triggered() { FormDoc *form = (FormDoc*)ui->mdiArea->activeSubWindow()->widget(); form->cut(); } void MainWindow::on_actionFont_triggered() { FormDoc *form = (FormDoc*)ui->mdiArea->activeSubWindow()->widget(); form->setFont(); } void MainWindow::on_actionPaste_triggered() { FormDoc *form = (FormDoc*)ui->mdiArea->activeSubWindow()->widget(); form->paste(); } void MainWindow::on_actionMDI_toggled(bool check) { if(check){ ui->mdiArea->setViewMode(QMdiArea::TabbedView); ui->actionPing->setEnabled(false); ui->actionExpand->setEnabled(false); //设置MDI子窗口的tab关闭按钮可以使用 ui->mdiArea->setTabsClosable(true); }else { ui->mdiArea->setViewMode(QMdiArea::SubWindowView); ui->actionPing->setEnabled(true); ui->actionExpand->setEnabled(true); } } void MainWindow::on_actionExpand_triggered() { ui->mdiArea->cascadeSubWindows(); } void MainWindow::on_actionPing_triggered() { ui->mdiArea->tileSubWindows(); }
标签:

Qt学习(五)自定义对话框,多窗口开发---添加设计师类,MDI多窗口开发由讯客互联电脑硬件栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Qt学习(五)自定义对话框,多窗口开发---添加设计师类,MDI多窗口开发