QT文本编辑器———第二弹(新建、打开、保存、另存为、退出)

QT文本编辑器———第二弹

一、实现文件菜单

文件
新建(&N)
打开(&O)
保存(&S)
另存为(&A)…
退出

二、效果演示

file_open...

三、代码

1.mainwindow.cpp

#include //对文件操作
#include 
#include 
#include 
#include 

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);   
/**************^_^丛林溪流^_^***************/
    this->setMaximumSize(1000,800);
    this->setMinimumSize(700,600);
    this->setWindowTitle("文本编辑器");
    this->setWindowIcon(QIcon(":/images/bear"));
    //this->setIconSize(QSize(50,50));//可以改变工具栏图标大小
    //1.设置中央布局组件
    textEdit = new QTextEdit(this);
    this->setCentralWidget(textEdit);

    //2.mainwindow添加状态栏
    statusBar = new QStatusBar(this);
    this->setStatusBar(statusBar);
    //label添加到状态栏的左侧
    label = new QLabel(this);
    statusBar->addWidget(label);

    //文本框内容改动后在文件名前显示*号
    connect(textEdit,&QTextEdit::textChanged,[&](){
        if(!label->text().contains('*'))
            label->setText(label->text()+'*');
    });
    //lineColumnLabel添加到状态栏的右侧
    lineColumnLabel = new QLabel(this);
    lineColumnLabel->setText("Ln:0 Col:0\t");
    statusBar->addPermanentWidget(lineColumnLabel);

    //3.添加滚动条
    textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);//设置垂直滚动条,属性设置为当在需要的时候显示
    // textEdit->setHorizontalScrollBarPolicy(Qt::ScrollB会arAsNeeded);
    //注意要点:在设置水平滚动条的时候碰到一个bug,因为setCentralWidget(textEdit)会内容自适应,和状态栏之间没有空隙给水平滚动条。
    //因此若用ui设计的中央布局组件,要留出一点位置给水平滚动条,不然无法显示。若用代码实现的,可以用以下另一种方式。
    textEdit->setLineWrapMode(QTextEdit::NoWrap);
}

注意要点1:这里在设置水平滚动条时,出现了bug。
垂直滚动条可以这样设置,但水平滚动条不能。

textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);//设置垂直滚动条,属性设置为当在需要的时候显示
//textEdit->setHorizontalScrollBarPolicy(Qt::ScrollB会arAsNeeded);

原因我分析的是,因为设置中央布局组件时setCentralWidget(textEdit)会内容自适应,导致textEdit和状态栏之间没有空隙给水平滚动条。所以水平滚动条用了另一种方式。

注意要点2:文本框内容改动后在文件名前显示*号,这里是模仿了记事本对改动过的文本的操作。

在这里插入图片描述

1.新建

注意要点:新建前如果有未保存的文本,应该有保存提示。若文本已经被保存,新建时会直接清空textEdit。最后一步清空textEdit,清空label。

void MainWindow::on_actionnew_triggered()//新建  新建前有文本,保存提示。若文本已经被保存,新建时会直接清空
{
    qDebug() << "newfile";
    //1、有‘*’,提醒用户是否保存文件
    int ret;
    if(label->text().contains('*')){
        ret = QMessageBox::warning(this, "注意", "是否保存文件", "是", "否");//获取返回值 0保存 1不保存
        qDebug() << ret;
    }
    if(ret == 0)//保存
    {
          MainWindow::on_actionsave_File_S_triggered();
    }
    else
    //2、清空textEdit,清空label
    textEdit->clear();
    label->clear();
}

2.打开

注意要点:打开文本前如果有未保存的文本,应该有保存提示,若文本已经被保存,打开时会直接清空textEidt。无论点击保存or不保存,之后一步都应该清空textEdit,清空label,为打开新文件做准备。

void MainWindow::on_actionopen_triggered()//打开   打开前有未保存的文本,保存提示。打开前若文本已经被保存,打开时会直接清空
{
    qDebug() << "openfile";
    //1、打开前有未保存的文本,有‘*’,提醒用户是否保存文件
    int ret;
    if(label->text().contains('*')){
        ret = QMessageBox::warning(this, "注意", "是否保存文件", "是", "否");//获取返回值 0保存 1不保存
        qDebug() << ret;
    }
    if(ret == 0)//保存
    {
          MainWindow::on_actionsave_File_S_triggered();
    }
    else
    //2、清空textEdit,清空label
    textEdit->clear();
    label->clear();

    //1. 弹出文件选择对话框
    QString filename = QFileDialog::getOpenFileName(this, "打开文本文件", "C:\\Users\\admin\\Desktop\\conglinxiliu", "txt (*.txt)");
    if(filename.isEmpty())//没有打开文件的操作
        return;
    //2. 读出文件内容到buf
    QFile f(filename);
    f.open(QIODevice::ReadOnly);
    QByteArray buf = f.readAll();
    f.close();
    //3. 显示在te
    textEdit->setText(buf);
    //4. 显示文件名到状态来
    label->setText(filename);
}

3.保存

注意要点:保存和另存为的区别;首先判断文本有没有被编辑。1.有被编辑(即标签含星号)且打开的文本有路径,点击保存默认保存在原路径 2.有被编辑但文本没有路径,点击保存弹出文件保存对话框,可以选择保存路径 3.文本未被修改时(即标签不含*),点击保存没有作用 4.最后一步都要清空标签的星号。

void MainWindow::on_actionsave_File_S_triggered()//保存   保存和另存为功能
{
    qDebug() << "savefile";
    //1.文本没有被编辑
    if(!label->text().contains('*'))//标签没有含‘*’
        return;
    //2.文本被编辑
    if(label->text().contains('*')){//标签含‘*’
    QString fileName = label->text();
    fileName.chop(1);//去掉标签的最后一个字符‘*’,以便保存时,文件名不显示‘*’
    if(fileName.isEmpty())
        fileName = QFileDialog::getSaveFileName(this,"保存文件","C:\\Users\\admin\\Desktop\\conglinxiliu","文本文档(*.txt);;word文档(*.doc)");//直接点保存为默认路径
    QFile f(fileName);//内容保存到路径文件
    f.open(QIODevice::WriteOnly);
        f.write(textEdit->toPlainText().toStdString().c_str());
        f.close();
       //3.消除标签的‘*’
    label->setText(fileName);
    }
}

4.另存为

注意要点:保存和另存为的区别;另存为百度解释,可以将打开的文件(不论有没修改过)保存到硬盘的任意一处,可存为任意名称,而不影响你目前打开的原文件。所以,另存为的判断条件和保存不同,不应该根据文本是否被编辑来判断,而是文件名不为空。最后一步依然要清除标签的星号。

void MainWindow::on_action_SaveAs_triggered()//另存为
//可以将打开的文件(不论有没修改过)保存到硬盘的任意一处,可存为任意名称,而不影响你目前打开的原文件
{
    qDebug() << "saveas_file";
    QString fileName = label->text();
    if(!fileName.isEmpty())
        fileName = QFileDialog::getSaveFileName(this,"保存文件","C:\\Users\\admin\\Desktop\\conglinxiliu","文本文档(*.txt);;word文档(*.doc)");//直接点保存为默认路径
    QFile f(fileName);//内容保存到路径文件
    f.open(QIODevice::WriteOnly);
        f.write(textEdit->toPlainText().toStdString().c_str());
        f.close();
       //消除标签的‘*’
    label->setText(fileName);
}

5.退出

注意要点:退出时,判断文本是否被保存(即标签是否有星号)。1.文本保存过,点击退出直接退出整个文本编辑器;2.文本未被保存,提醒用户保存文件,点击保存调保存函数即可,不保存时退出整个文本编辑器。

void MainWindow::on_action_exit_triggered()//退出   
{
    qDebug() << "closefile";
    //1.检测状态栏有‘*’号,弹出消息提示对话框,提醒用户保存文件
    int ret;
    if(label->text().contains('*'))
        ret = QMessageBox::information(this,"提示","是否保存文件","是","否");//用ret去接收返回值,0保存,1不保存
     if(ret == 0)
     {
         MainWindow::on_actionsave_File_S_triggered();//调保存函数
     }
     else
         this->close();//关闭窗体,不保存时退出整个文本编辑器
}

2.mainwindow.h

private slots://槽函数
    void on_actionopen_triggered();

    void on_actionnew_triggered();

    void on_actionsave_File_S_triggered();
    
    void on_action_exit_triggered();

    void on_action_SaveAs_triggered();
private:
    Ui::MainWindow *ui;
    QTextEdit  *textEdit;
    QLabel     *label,*lineColumnLabel;//状态栏的左标签、右标签,分别显示文件路径和光标定位第几行第几列
    QStatusBar *statusBar;

四、反思总结

五个子菜单的功能没有想象中的复杂,主要是逻辑以及分析每个子菜单的判断条件,其中”打开“这个子菜单功能分析要稍微复杂一些,但仔细发现其实就是步骤多了一点,判断星号这段代码,几个子菜单都可以共用。
注意要点做了详细阐述,代码中也写了注释,这也是博主在写代码时遇到的一些问题。
后续内容还会陆续更新哟~

你可能感兴趣的:(qt,ui,qt,开发语言,编辑器,ui,c++)