当前位置: 首页 > news >正文

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
  • 知识点2QStringListModel模型获取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的位置都修改成mainwindow2Mainwindow2,声明#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
  • 知识点1mianwindow里面的组件,实际的操作对象是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();
}

相关文章:

  • ARM TCM(itcm和dtcm)
  • 如何用ollama快速布署deepseek-r1大模型
  • 学习数据结构(11)二叉树(堆)下
  • tauri-plugin-http插件暂时不支持流传输Streaming,所以大模型的流传输就难了,所以还是用js的请求吧
  • Elasticsearch7.1.1 配置密码和SSL证书
  • 从猜想终结到算法革新,弹性哈希开启数据存储新篇章
  • 【科研绘图系列】R语言绘制SCI论文图合集
  • 飞行器的,偏航角,俯仰角,横滚角,的图解。加动图演示。
  • React入门案例-Hello React案例
  • Python编程之数据分组
  • 机器视觉--图像的参数
  • vscode将文件中行尾默认CRLF改为LF
  • 12.1 Android中协程的基本使用
  • 如何在 ConstraintLayout 中将 ViewPager 始终置于 ll_title 的下方
  • 前端需要学习 Docker 吗?
  • 【运维】源码编译安装cmake
  • 【C++】The fundamentals of C++
  • Spring 接入 DeepSeek
  • AD(Altium Designer)器件封装——立创商城导出原理图和PCB完成器件封装操作指南
  • 达梦存储过程执行后 sql日志信息粗读
  • 习近平向“和平薪火 时代新章——纪念中国人民抗日战争和苏联伟大卫国战争胜利80周年中俄人文交流活动”致贺信
  • 联想发布超级智能体矩阵,杨元庆:美国关税影响反映在产品定价上,未来不确定性很大
  • A股三大股指收涨:军工股掀涨停潮,两市成交近1.5万亿元
  • 央行:5月8日起,下调个人住房公积金贷款利率0.25个百分点
  • 这个接班巴菲特的男人,说不出一个打动人心的故事
  • 默茨在德国联邦议院第一轮投票中未能当选总理