QT实现记事本学习笔记

1.读取中文内容文件的乱码问题

在QT中,用QTextStream处理文件的内容会更好,同时可以通过 QTextCodec::codecForName() 方法在 QTextStream 中进行设置。

void Widget::on_btnstrRead_clicked()

{

    QFile file;

    file.setFileName("C:/Users/Administrator/Desktop/test.txt");

    if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){

        qDebug() << "file open error";

    }

    QTextStream in(&file);

    in.setCodec("UTF-8");

   // QString context = in.read(file.size());

    while(!in.atEnd()){

        QString context = in.readLine();

        qDebug() << context;

        qDebug() << "--------";

    }

    file.close();

}

以上代码在运行后读取中文内容的文件时会出现乱码,主要原因我发现是因为我自己的电脑默认的文档保存编码是ANSI,然后这些代码是UTF8编码来读取和写入文件,所以才会乱码

所以需要先通过代码将电脑保存的文档转换成utf8,对读取的内容重新编码,让文档编码跟我写的读取编码匹配

void Widget::on_btnstrRead_clicked()

{

    //打开文件

    QFile file("C:/Users/Administrator/Desktop/test.txt");

    if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){

        qDebug() << "Open File Error";

    }

    //读取文件

    QTextStream in(&file);

    //in.setCodec("UTF-8");

    QTextCodec *codec = QTextCodec::codecForName("UTF-8");

    //int size = file.size();

    //QString context = in.read(size);//整个文件读取,弊端:文件太大时

    while (!in.atEnd()) {

        QString context = in.readLine();

        QString string = codec->fromUnicode(context);

        qDebug()<<string;

        qDebug() << "--------";

    }

    file.close();

}

2.窗口大小变化时,里面的布局会随之变化

this->setLayout(ui->verticalLayout);

ui->widgetBottom->setLayout(ui->horizontalLayout);

3.信号与槽的4种连接方式

Widget::Widget(QWidget *parent) :

    QWidget(parent),

    ui(new Ui::Widget)

{

    ui->setupUi(this);

    //第二种方式:QObject::connect(sender,SIGNAL(signal()),receiver, SLOT(slot()));

    QObject::connect(ui->btn_connect,SIGNAL(clicked()),this,SLOT(on_connButton_clicked()));

    //第三种方式:用lambda表达式QObject::connect(sender,&Sender::signal, [=]() {/* lambda body */ }); 接收者没写就默认为this,并且无需在头文件声明

    QObject::connect(ui->LambdaBtn,&QPushButton::clicked, [=]() {

        qDebug()<<"btnlambda_Button";

    });

    //第四种方式:使用函数指针,QObject::connect(sender,&Sender::signal, receiver,&Receiver::slot);

    QObject::connect(ui->btnFortch,&QPushButton::clicked, this,&Widget::on_fortchButton_clicked);

}

Widget::~Widget()

{

    delete ui;

}

//第一种方式:通过uiDesigner

void Widget::on_pushButton_clicked()

{

    qDebug()<<"btnui_Button";

}

void Widget::on_connButton_clicked()

{

    qDebug()<<"btnconnect_Button";

}

void Widget::on_fortchButton_clicked()

{

    qDebug()<<"btnfortch_Button";

}

4.QComboBox

如果要做个记事本支持字符编码

获取用户在QComboBox上选择的字符编码,用特定编码打开文件,这里注意QComboBox返回QString 类型, setCodec参数要求const char*型 QString先转成C++的String,再转换成const char *

void Widget::on_btnOpen_clicked()

{

    QString fileName = QFileDialog::getOpenFileName(this,

          tr("Open Image"), "C:/Users/Administrator/Desktop", tr("Text files (*.txt)"));

    // 清空文本编辑器的内容

    ui->textEdit->clear();

    // 设置 QFile 对象的文件名

file.setFileName(fileName);

//以只读和文本模式打开文件

if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){

//如果打开文件失败,输出错误信息

        qDebug() << "Open File Error";

    }

    //打开文件就能把文件名弄到窗口标题栏以指明打开了什么文件

    this->setWindowTitle(fileName + "- cxq的记事本");

    //创建 QTextStream 用于读取文件内容

    QTextStream in(&file);

    // 从下拉框获取当前选中的字符编码

QString str = ui->comboBox->currentText();

// 将 QString 转化为 char* 类型

    const char* c_str = str.toStdString().c_str();

    //QTextCodec *codec = QTextCodec::codecForName(c_str);

in.setCodec(c_str);

// 循环读取文件直到结束

while (!in.atEnd()) {

// 读取文件的一行

        QString context = in.readLine();

        //QString string = codec->fromUnicode(context);

// 将读取的内容追加到文本编辑器

        ui->textEdit->append(context);

    }

}

支持打开文件后进行字符编码的重新选择和显示加载

 //1. 在Widget的构造函数中关联信号与槽,检测用户选择条目的信号。connect(ui->comboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(onCurrentIndexChanged(int)));

//2. 添加槽函数,当用户选择信号后被调用,判断是否当前有打开的文件,如果有,则重新用新的编码读取文件并重新显示。

// onCurrentIndexChanged 方法:当 QComboBox 的选中项变化时执行

void Widget::onCurrentIndexChanged(int)

{

    ui->textEdit->clear();

    if(file.isOpen()){

        //读取文件

        QTextStream in(&file);

        // 从下拉框获取当前选中的字符编码

        QString str = ui->comboBox->currentText();

        const char* c_str = str.toStdString().c_str();

        in.setCodec(c_str);

        //将文件指针移动到文件开始位置

        file.seek(0);

        while (!in.atEnd()) {

            // 循环读取文件直到文件结束

            QString context = in.readLine();

            //将读取的内容追加到文本编辑器

            ui->textEdit->append(context);

        }

    }

}

5.QList

QList 是一个容器类,它在内部实现上类似于一个数组,但也提供了一些链表的特性。

 QList 的内部工作原理:

  1. 数组式存储: QList 在大多数情况下使用连续内存存储其元素,类似于数组。提供了快速的索引访问(通过下标操作符 [] ),以及有相对高效的迭代性能。
  2. 动态调整大小:与静态数组不同, QList 可以动态增长和缩减,自动管理内存分配。
  3.  链表特性:虽提供了一些链表的操作,比如在列表的开始或结束处添加和移除元素。
  4.  复制时共享内存: QList 使用一种称为“隐式共享”(implicit sharing)或“写时复制”(copy-onwrite)的技术。即复制一个 QList 时,它不会立即复制所有元素,而是共享相同的数据,直到尝试修改其中一个列表,此时才进行实际的复制。

使用场景: 当需要快速的随机访问(如通过索引访问元素)时, 或者你的主要操作是在列表的两端添加或移除元素

基本用法

包含头文件

#include <QList>

创建 QList 实例

QList<int> list;

添加元素:使用 append 或 push_back 方法添加元素。

list.append(1);

访问元素:可以使用下标操作符或 at() 方法访问元素。

int firstElement = list[0];

int secondElement = list.at(1);

遍历列表:使用迭代器或范围基的 for 循环遍历列表。

for(int i = 0; i < list.size(); ++i) { // size = sizeof(arr)/sizeof(arr[0])

qDebug() << list[i];}

// 或者使用范围基的 for 循环

for(int item : list) {qDebug() << item;}

移除元素:使用 removeAt 、 removeOne 或 clear 方法移除元素。

list.removeAt(1); // 移除索引为 1 的元素

list.removeOne(3); // 移除一个值为 3 的元素

list.clear(); // 清空整个列表

6.QTextEdit

参考:https://blog.youkuaiyun.com/m0_74014525/article/details/138169656?ops_request_misc=&request_id=&biz_id=102&utm_term=QTextEdit&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-138169656.142^v100^pc_search_result_base9&spm=1018.2226.3001.4187

应用:

①添加行列显示

使用QTextEdit的cursorPositionChanged信号,当光标发生移动时候刷新显示

在构造函数中添加信号与槽

connect(ui->textEdit,SIGNAL(cursorPositionChanged()),this,SLOT(onCursorPositionChanged()));

槽函数

//获取textEdit的行列并显示到QLabel上

void Widget::onCursorPositionChanged()

{

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

    //QString::number从数值转换成QString

    QString blockNum = QString::number(cursor.blockNumber()+1);

    QString columnNum = QString::number(cursor.columnNumber()+1);

    const QString labelMes= "第"+blockNum+"行"+"第"+columnNum+"列"+"       ";

    ui->labelPosition->setText(labelMes);

②设置当前行高亮

获取当前行的光标位置,使用的信号和获取行列值是一样的,通过QTextEdit::ExtraSelection 来配置相关属性,它是一个在 QTextEdit 中用来表示额外的文本选择和高亮的结构。

//设置当前行高亮

    QList<QTextEdit::ExtraSelection> extraSelections;

    QTextEdit::ExtraSelection ext;

    //1.知道当前行

    ext.cursor = cursor;

    QBrush qBrush(Qt::yellow);

    //2.颜色

    ext.format.setBackground(qBrush);

    //3.配置段属性,整行显示

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

    //4.设置

    extraSelections.append(ext);

ui->textEdit->setExtraSelections(extraSelections);

}

7.使用初始化列表

初始化列表紧跟在构造函数参数列表后面,以冒号( : )开始,后跟一个或多个初始化表达式,每个表达式通常用逗号分隔。

class MyClass

{

private:

int a;

double b;

std::string c;

public:// 使用初始化列表来初始化字段

MyClass(int x, double y, const std::string& z) : a(x), b(y), c(z) {

// 构造函数体

}

MyClass 有三个成员变量:a、b和 c 。当创建 MyClass 的一个实例时,通过构造函数传递三个参数,这些参数 被用于通过初始化列表直接初始化成员变量。初始化列表 : a(x), b(y), c(z) 的意思是用 x 初始化 a ,用 y 初始化 b ,用 z 初始化 c 。

8.实现快捷键功能

使用QShortcut 类

// 制作两个快捷键

QShortcut *shortcutOpen = new QShortcut(QKeySequence(tr("Ctrl+O", "File|Open")),this);

QShortcut *shortcutSave = new QShortcut(QKeySequence(tr("Ctrl+S", "File|Save")),this);

// 把Ctrl+O的信号添加槽,调用打开按键的槽函数

connect(shortcutOpen,&QShortcut::activated,[&](){

        Widget::on_btnOpen_clicked();

    });

// 把Ctrl+S的信号添加槽,调用保存按键的槽函数

    connect(shortcutSave,&QShortcut::activated,[&](){

        Widget::on_btnSave_clicked();

    });

实现字体放大缩小功能

QShortcut *shortcutZoomIn = new QShortcut(QKeySequence(tr("Ctrl+Shift+=")),this);    QShortcut *shortcutZoomOut = new QShortcut(QKeySequence(tr("Ctrl+Shift+-")),this); connect(shortcutZoomIn,&QShortcut::activated,[&](){Widget::zoomIn(); });    connect(shortcutZoomOut,&QShortcut::activated,[&](){Widget::zoomOut();});
void Widget::zoomIn()
{    
//获得当前的字体信息   
 QFont font = ui->textEdit->font();    
//获得当前字体的大小   
 int fontsize = font.pointSize();    
if(fontsize == -1) return;   
 //改变大小,并设置字体大小   
 int newFontSize = fontsize + 1;   
 font.setPointSize(newFontSize);  
  ui->textEdit->setFont(font);
}
void Widget::zoomOut()
{    
//获得当前的字体信息    
QFont font = ui->textEdit->font();    
//获得当前字体的大小    
   int fontsize = font.pointSize();    
   if(fontsize == -1) return;   
 //改变大小,并设置字体大小   
   int newFontSize = fontsize - 1;    
   font.setPointSize(newFontSize);   
   ui->textEdit->setFont(font);
}

9.事件

事件会经过:事件派发 -> 事件过滤->事件分发->事件处理几个阶段。

事件分发器会将分类之后的事件(鼠标事件、键盘事件、绘图事件...)分发给对应的事件处理器函数(在QWidget类的Protected Funtion)进行处理,每个事件处理器函数都有默认的处理动作(也可以重写这些事件处理器函数),无需再显示去调用,当用户触发事件时,就会自动回调每个事件处理器函数

应用:事件方式实现字体放大缩小

自定义控件MyTextEdit

同时也无需再改之前写好的文本框实现代码

头文件

源文件:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值