Qt小项目案例:记事本

Day1 简单的页面设计

Day2 信号和槽的实现

一:学到的重点

1 QFileDialog::getSaveFileName :

2 QFileDialog::getOpenFileName :

3 Text (*.txt)和 QIODevice::Text

其中Text是Qt的文件过滤器。它指定了对话框中显示的文件类型。这里的过滤器是 Text (*.txt),表示只显示 .txt 文件。用户也可以手动输入其他文件类型。

QIODevice::Text 主要用于确保文本文件在不同平台上的换行符一致性。

4 QTextStream out(&file);

QTextStream out(&file); 是 Qt 框架中用于创建一个文本流对象并将其与文件关联的代码。通过 QTextStream,你可以方便地以文本形式读写文件内容。

5 QString context=ui->textEdit->toPlainText();

toPlainText()QTextEdit 类的一个成员函数,其作用是获取 QTextEdit 控件中的纯文本内容,返回值类型为 QString。这个函数会忽略文本中的富文本格式,仅返回文本本身。

QString context=ui->textEdit->toPlainText();

6 QComboBox

二:3个按钮实现

注意:我设置的打开和保存编码格式为UTF-8

打开:

保存:

1 打开按钮

//点击打开按钮实现 打开本地电脑文件

void MainWindow::on_btnOpen_clicked()
{
    //得到文件路径
    QString path;
    //得到文件路径 "Text (*.txt))"筛选作用 当打开文件的时候只出现文件夹和txt结尾的文件
    //QIODevice::Text 主要用于确保文本文件在不同平台上的换行符一致性。
    path=QFileDialog::getOpenFileName(this,"打开文件","C:\\Users\\50192\\Desktop","Text (*.txt)");
    QFile file(path);
    //设置打开方式 只读方式
    file.open(QIODevice::ReadOnly);
    
    //如果打开方式不是只读或者不符合Qt的换行符打开失败
    if(!file.open(QIODevice::ReadOnly|QIODevice::Text)){
        qDebug()<<"file open error";
    }
    //利用QByteArray对象数组存储file对象里面的内容 然后显示在ui界面上
    //file.readAll();读取全部内容
    QByteArray arry=file.readAll();
    //读取到的数据放入text中
    //ui->textEdit->setText(arry);
    //按照codec设置的编码格式读取数据
    ui->textEdit->setText(codec->toUnicode(arry));
    file.close();
    
}

解决编码问题时候 修改后

//点击打开按钮实现 打开本地电脑文件

void MainWindow::on_btnOpen_clicked()
{
    //得到文件路径
    QString path;
    //得到文件路径 "Text (*.txt))"筛选作用 当打开文件的时候只出现文件夹和txt结尾的文件
    //QIODevice::Text 主要用于确保文本文件在不同平台上的换行符一致性。
    path=QFileDialog::getOpenFileName(this,"打开文件","C:\\Users\\50192\\Desktop","Text (*.txt)");
    QFile file(path);
    //如果打开方式不是只读或者不符合Qt的换行符打开失败
    if(!file.open(QIODevice::ReadOnly|QIODevice::Text)){
        qDebug()<<"file open error";
    }



    QTextStream out(&file);
    //输出当前编码
    qDebug()<<ui->comboBox->currentText().toStdString().c_str();
    //设置输入的字符编码
    //设置文件编码格式
    //ui->comboBox->currentText().toStdString().c_str()作用
    //把原来的ui->comboBox->currentText()的QString转换为char *
    out.setCodec(ui->comboBox->currentText().toStdString().c_str());

    //下面这些在读取的时候不能修改编码格式
    
    //利用QByteArray对象数组存储file对象里面的内容 然后显示在ui界面上
    //file.readAll();读取全部内容
//        QByteArray arry=file.readAll();
//        //读取到的数据放入text中
//        //ui->textEdit->setText(arry);
//        //按照codec设置的编码格式读取数据
//        ui->textEdit->setText(arry);
    while(!out.atEnd()){
        QString context=out.readLine();
        ui->textEdit->append(context);
    }
    file.close();

}

2 保存按钮

//保存按钮实现
void MainWindow::on_btnSqve_clicked()
{
    //得到文件路径
    QString path;
    //得到文件路径 调用保存函数
    //"Text (*.txt *.doc)" 是当文件没有后缀名的时候默认是 txt 和 doc
    path=QFileDialog::getSaveFileName(this,"打开文件","C:\\Users\\50192\\Desktop","Text (*.txt *.doc)");
    QFile file(path);
    //等同于上面的代码
    //file.setFileName(path);
    //设置打开方式 只写方式
    file.open(QIODevice::WriteOnly);
    QTextStream out(&file);
    //设置输入的字符编码
    out.setCodec("UTF-8");
    //这行代码的主要功能是从 QTextEdit 控件里获取纯文本内容,并且把获取到的文本存储在 QString 类型的变量 context 中。
    QString context=ui->textEdit->toPlainText();
    out<<context;
    file.close();
}

3 删除按钮

点击差号 清空窗口里面的内容


//点击差号 清空窗口里面的内容
void MainWindow::on_btnClose_clicked()
{

   ui->textEdit->clear();
}

Day3:编码问题的解决

一:学到的重点

1 file.seek(0)

设置光标的位置

2 ui->comboBox->currentText().toStdString().c_str()

toStdString().c_str()将QString转化为char *

3 Qt识别中文

重新打开Qt文件 在选项中选中工具 在选中utf-8

4 QTextCursor cursor=ui->textEdit->textCursor();

QTextCursor cursor = ui->textEdit->textCursor(); 这行代码的主要作用是从 QTextEdit 控件中获取当前的文本光标对象

5 ext.format

format是TextEdit设置文本格式

//设置ext的属性 整行显示

ext.format.setProperty(QTextFormat::FullWidthSelection,true);

6 currentContent.mid(originalContent.length());

  • mid()QString 类的成员函数,它用于从字符串中提取子字符串。mid() 函数有两个重载版本,这里使用的是 mid(int position, int n = -1) 这个版本,其中 position 是起始位置,n 是要提取的字符数(如果 n 为 -1,则提取从 position 开始到字符串末尾的所有字符)。
  • 在这行代码中,originalContent.length() 作为 mid() 函数的 position 参数,意味着从 currentContent 字符串中从 originalContent 的长度位置开始提取子字符串。由于 originalContent 存储的是文件打开时的原始内容,currentContent 是当前编辑框中的全部内容,所以从 originalContent 的长度位置开始提取的子字符串就是用户在打开文件后新添加的内容。例如,如果 originalContent 是 “Hello”,currentContent 是 “Hello, World!”,那么 originalContent.length() 为 5,currentContent.mid(originalContent.length()) 就会返回 “, World!”,即新增的内容。

二 :编码问题的解决

出现的问题:读取文件的时候只能读取UTF-8类型的文本 当打开其他编码时候出现乱码

currentIndexChanged(int) 选中不同的的选项的时候发送信号

前面三个按钮里面的file.close()注释掉 否则该功能不能实现 上面我自己写错了 因为还在操作文件中不能关闭文件

void MainWindow::On_CurrentIndex_Changed(int)函数的实现

//调用槽函数实现把当前的文本转化为当前编码格式并读取
void MainWindow::On_CurrentIndex_Changed(int){
    ui->textEdit->clear();
    
    if(file.isOpen()){
        qDebug()<<"file is Open";
        QTextStream out(&file);
        
        out.setCodec(ui->comboBox->currentText().toStdString().c_str());
        
        //在打开按钮中光标在文件的末尾 所以读取不成功
        //设置光标恢复到0位置
        file.seek(0);
        while(!out.atEnd()){
            QString context=out.readLine();
            ui->textEdit->append(context);
        }
    }
    else{
        qDebug()<<"error open ";
    }
    
    
}

三:显示光标的位置

创建信号和槽

cursorPositionChanged()光标以改变就发送信号

槽函数实现

QTextCursor cursor = ui->textEdit->textCursor(); 这行代码的主要作用是从 QTextEdit 控件中获取当前的文本光标对象

//得到光标的坐标并把坐标在界面上显示
void MainWindow::OnCursorPositionChanged()
{
    QTextCursor cursor=ui->textEdit->textCursor();
    //把得到的行和列强制转为字符串
    //得到列
    QString col=QString::number(cursor.columnNumber()+1);
    //得到行
    QString line=QString::number(cursor.blockNumber()+1);
    const QString str="L :"+line+" "+"C :"+col+" ";
    ui->label_2->setText(str);
}

四:实现当前行高亮

void MainWindow::OnCursorPositionChanged()
{
    //这行代码的主要作用是从 QTextEdit 控件中获取当前的文本光标对象
    QTextCursor cursor=ui->textEdit->textCursor();
    //把得到的行和列强制转为字符串
    //得到列
    QString col=QString::number(cursor.columnNumber()+1);
    //得到行
    QString line=QString::number(cursor.blockNumber()+1);
    const QString str="L :"+line+" "+"C :"+col+" ";
    ui->label_2->setText(str);


    //设置当前行高亮

    //QTextEdit::ExtraSelection是利用类模板完成的
    //设置能存储QTextEdit::ExtraSelection的list
    QList<QTextEdit::ExtraSelection> extraSelections;
    //设置QTextEdit::ExtraSelection的对象
    QTextEdit::ExtraSelection ext;
    //得到当前行
    ext.cursor=cursor;
    //设置颜色 Qt::lightGray为灰色
    QBrush qb(Qt::lightGray);
    //format是设置文本格式
    ext.format.setBackground(qb);
    //设置ext的属性 整行显示
    ext.format.setProperty(QTextFormat::FullWidthSelection,true);
    //把QTextEdit::ExtraSelection对象放入到list种
    extraSelections.append(ext);

    //把设置的extraSelections放入textEdit中
    ui->textEdit->setExtraSelections(extraSelections);

}

五:优化保存按钮

当没有打开文件时候跳出选择文件窗口 当打开过文件的时候不跳出直接写入

修改打开按钮

如果是下面代码打开时候会清空内容

文件被清空的原因是因为你使用了 QIODevice::WriteOnly 模式来打开文件。QIODevice::WriteOnly 模式会清空文件内容,并将文件指针定位到文件的开头,以便你可以从头开始写入数据。

 if(!file.open(QIODevice::WriteOnly|QIODevice::Text)){
        qDebug()<<"file open error";
    }

在上面的基础运行会出现bug(出现追加内容重复的问题,是因为在以追加模式保存时,把整个文本编辑框的内容都追加到文件里了)

解决方法:在头文件中定义originalContent用了存储打开我文件的原内容

在打开按钮中修改:

  • mid()QString 类的成员函数,它用于从字符串中提取子字符串。mid() 函数有两个重载版本,这里使用的是 mid(int position, int n = -1) 这个版本,其中 position 是起始位置,n 是要提取的字符数(如果 n 为 -1,则提取从 position 开始到字符串末尾的所有字符)。

void MainWindow::on_btnSqve_clicked()
{
    qDebug()<<"5858";
    if(!file.isOpen()){
        //得到文件路径
        QString path;
        //得到文件路径 调用保存函数
        //"Text (*.txt *.doc)" 是当文件没有后缀名的时候默认是 txt 和 doc
        path=QFileDialog::getSaveFileName(this,"保存文件","C:\\Users\\50192\\Desktop","Text (*.txt *.doc)");

        //设置当前保存的文件名称
        this->setWindowTitle(path+"——小张记事本sl");

        //QFile file(path);
        //等同于上面的代码
        file.setFileName(path);
        //设置打开方式 只写方式
    }
    //    //file.open(QIODevice::WriteOnly);
    //    QTextStream out(&file);
    //    //设置输入的字符编码
    //    out.setCodec(ui->comboBox->currentText().toStdString().c_str());
    //    //这行代码的主要功能是从 QTextEdit 控件里获取纯文本内容,并且把获取到的文本存储在 QString 类型的变量 context 中。
    //    out<<ui->textEdit->toPlainText();


    //重新关闭才能实现下面的if判断
    file.close();
    
    QString currentContent = ui->textEdit->toPlainText();
    //mid() 是 QString 类的成员函数,它用于从字符串中提取子字符串。mid() 函数有两个重载版本,这里使用的是 mid(int position, int n = -1),
    //这个版本,其中 position 是起始位置,n 是要提取的字符数(如果 n 为 -1,则提取从 position 开始到字符串末尾的所有字符)
    //从原来打开的文件长度读取,意味着newContent里面存储的是新加入的内容
    QString newContent = currentContent.mid(originalContent.length()); // 获取新增的内容

    // 以追加和文本模式打开文件
       if (file.open(QIODevice::Append | QIODevice::Text)) {
           QTextStream out(&file);
           // 设置输出的字符编码
           out.setCodec(ui->comboBox->currentText().toStdString().c_str());
           // 将新增的内容写入文件
           out << newContent;
           file.close();
           originalContent = currentContent; // 更新原始内容
           QMessageBox::information(this, "保存成功!", "文件已成功保存!");
       } else {
           // 处理文件打开失败的情况
           QMessageBox::critical(this, "保存失败!", "无法打开文件进行保存!");
       }

}

五:优化关闭按钮

//点击差号 清空窗口里面的内容
void MainWindow::on_btnClose_clicked()
{
    QMessageBox msgBox;
    msgBox.setText("The document has been modified.");
    msgBox.setInformativeText("Do you want to save your changes?");
    msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
    msgBox.setDefaultButton(QMessageBox::Save);
    int ret = msgBox.exec();
    switch (ret) {
      case QMessageBox::Save:
          //调用保存按钮的功能
          on_btnSqve_clicked();
          break;
      case QMessageBox::Discard:
          ui->textEdit->clear();
          if(file.isOpen()){
              file.close();
              this->setWindowTitle("小张记事本sl");
          }
          break;
      case QMessageBox::Cancel:

          break;
      default:
          // should never be reached
          break;
    }
}

六:添加打开和保存的快捷键

 //创建打开快捷键
    QShortcut * shortcut_Open=new QShortcut(QKeySequence(tr("Ctrl+O","File|Open")),this);

    //创建保存快捷键
    QShortcut * shortcut_Save=new QShortcut(QKeySequence(tr("Ctrl+S","File|Save")),this);

    //连接快捷键
    connect(shortcut_Open,&QShortcut::activated,[=](){

        on_btnOpen_clicked();
    });
    connect(shortcut_Save,&QShortcut::activated,[=](){
        qDebug()<<"58589999999111111";
        on_btnSqve_clicked();
    });

六:添加字体放大和缩小快捷键

定义放大和缩小的函数

void MainWindow::zoomOut()
{
    //获取当前textEdit字体的信息
    QFont font=ui->textEdit->font();
    //获取当前字体大小
    int fontSize=font.pointSize();
    if(fontSize==-1){
        return;
    }
    //字体大小加一
    int newfontsize=fontSize+1;
    //把增大的字体放入font中
    font.setPointSize(newfontsize);
    //把修改后的font放入textEdit中
    ui->textEdit->setFont(font);


}

void MainWindow::zoomIn()
{
    //获取当前textEdit字体的信息
    QFont font=ui->textEdit->font();
    //获取当前字体大小
    int fontSize=font.pointSize();
    if(fontSize==-1){
        return;
    }
    //字体大小加一
    int newfontsize=fontSize-1;
    //把增大的字体放入font中
    font.setPointSize(newfontsize);
    //把修改后的font放入textEdit中
    ui->textEdit->setFont(font);
}

设置快捷键

连接快捷键

Day4:利用鼠标的滚轮进行字体的放大和缩小

一:学到的重点

1 重写事件

在重写事件操作的时候最后大部分要交给父类处理

2 事件过滤器

先进行注册事件 ui->textEdit->installEventFilter(this);

在重写eventFilter(QObject *watched, QEvent *event){}

3 强制类型转换

static_cast

static_cast 是 C++ 中最常用的类型转换方式之一,它在编译时进行类型检查,不进行运行时的安全性检查。适用于具有明确定义的类型转换,比如基类和派生类之间的转换、数值类型之间的转换等。

bool MyTextEdit::eventFilter(QObject *watched, QEvent *event){
//将QEvent强制转换为QWheelEvent类型
QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event);
}

二:事件重写来完成

第一步:建立文件

第二步:完善文件

第三步:定义和重写事件

第五步:实现上面函数

void MyTextEdit::wheelEvent(QWheelEvent *event)
{
    if(this->flag==1){
        //鼠标滚轮的数据
        qDebug()<<event->angleDelta().y();
        if(event->angleDelta().y()>0){
            //字体放大
            // m->zoomOut1();
            zoomOut();

        }
        else{
            //字体缩小
            //m->zoomIn1();
            zoomIn();
        }

    }
    //其他的操作交给父类处理
    QTextEdit::wheelEvent(event);
}

void MyTextEdit::keyPressEvent(QKeyEvent *event)
{
    if(event->key()==Qt::Key_Control){
        this->flag=1;
    }
      //其他的操作交给父类处理
    QTextEdit::keyPressEvent(event);
}

void MyTextEdit::keyReleaseEvent(QKeyEvent *event)
{
    if(event->key()==Qt::Key_Control){
        this->flag=0;
    }
      //其他的操作交给父类处理
     QTextEdit::keyReleaseEvent(event);
}

注意:其中flag是一个标志按下ctrl时候flag=1 释放ctrl时候flag=0 为1的时候滚轮进行滑动才进行放大和缩小

QTextEdit::keyPressEvent(event);必须有这个 因为其他的操作交给父类处理 否则不能滚动滚轮实现上下文翻页在写完事件重写后最后必须要交给父类处理

二:事件过滤器来完成

第一步:在主窗口中注册事件过滤器

第二步:在类文件中重写事件过滤器

第三步:完成事件过滤器函数

//利用事件过滤器完成鼠标滚动
bool MyTextEdit::eventFilter(QObject *watched, QEvent *event)
{
    if(event->type()==QEvent::Wheel){
        QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event);
        if (wheelEvent->modifiers() & Qt::ControlModifier) {
             if(wheelEvent->angleDelta().y()>0){
                 zoomOut();
             }
             if(wheelEvent->angleDelta().y()<0){
                 zoomIn();
             }
        }

        return true;
        }
    return false;


    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值