学习C++、QT---25(QT中实现QCombobox库的介绍和用QCombobox设置编码和使用编码的讲解)
每日一言
你流过的汗水,终将成为照亮前路的光。
QcomboBox
我们引入这个知识点的目的是为了做出
我们想要自己切换编码的这个效果,就是因为之前我们在遇到如果不是相同编码时会发生乱码的现象,那么我们无法处理,而且我们的用户不可能直接去我们的代码去更改,那么我们需要解决这个问题。
涉及到QCombobox这个类
我们添加上对应的普遍的编码
那我们设置的话,依旧去帮助文档搜索QCombobox这个库,那么我们会看到这个
这个函数就是我们点击切换编码的时候会发送对应的信号,这个currentindexchanged就是信号,那么我们需要进行信号与槽的绑定啊,
记住我们的这个信号与槽的绑定要在构造函数;里面去进行绑定(回顾一下)
QObject::connect(ui->comboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(on_currentIndexChanged(int)));
定义槽函数
实现槽函数
实现槽函数这边我们进行输出这个index,还有输出当前选择的编码信息,这个编码信息就是调用ui->comboBox->currentText()这个就就可以将文本输出出来
这样我们看实验现象
我们会发现,我们点击QComboBox的切换不同的编码的时候
会将这个index输出出来,这个index的值就是我们点击切换编码的时候,这个index代表着编码的顺序,作为index的值,那么这个index的值会自动注入到这个槽函数的实现中
好的那么我们可以根据这个现象,进行将功能继续完善移植到我们的这个记事本中
回过头来,我会发现,用这个也可以啊
这个qPrintable() 这样在输出控制台可以去除两边的引号,看起来更舒服
Qcombobox应用到记事本项目中
老样子,先去信号与槽的绑定
我们设置编码的时候,我们想要编码的切换后,是这样的效果,那么我们肯定是需要先将我们的之前编码不相同的文本进行clear掉,那么再去重新的读取相同的文件,这个就是我们转编码读取文件的原理
好的我们现在展示代码
首先这个
ui->textEdit->clear(); //这个是用于清空当前记事本的textEdit的文本
if(file.isOpen()){
QTextStream in(&file); //创建一个对象与file文件关联
in.setCodec(ui->comboBox->currentText().toStdString().c_str());
file.seek(0); //用于文件指针的重置到文件打开的初始状态
while(!in.atEnd()){
QString context = in.readLine();
ui->textEdit->append(context);//追加到文本的末尾
}
- 那么会有一个问题
- 我们会发现怎么有两个QTextStream对象,这个是确实的,我们的想法没有错
- 两个QTextStream对象确实不同,但它们操作同一个文件,导致文件指针位置共享。
- 通过重置文件指针(file.seek(0))和统一编码设置,可以解决读取和显示问题。
in.setCodec(ui->comboBox->currentText().toStdString().c_str());这个有说法
会发现我们的这个setcodec和这个currentText的返回值类型是不一样的,setcodec是char *(也就是c风格的字符串)currentText是QString类型那么我们就需要进行转换
涉及到Qstring转换成char * 型
那么我们的参数ui->comboBox->currentText().toStdString().c_str()需要写成这样
ui->comboBox->currentText().这个是取出当前combobox的text值“UTF-8”、“GBK”等等,就像之前我们自己把编码写死一样,但是我们现在是灵活的选择编码
随后进行转换需要用到.toStdString().c_str()也就是先转换成C++的string类型再转换成c风格的char *
这个写法和函数我们要记住
再回到我们的代码这边
if(file.isOpen()){
QTextStream in(&file); //创建一个对象与file文件关联
in.setCodec(ui->comboBox->currentText().toStdString().c_str());
file.seek(0); //用于文件指针的重置到文件打开的初始状态
while(!in.atEnd()){
QString context = in.readLine();
ui->textEdit->append(context);//追加到文本的末尾
}
为什么要用到这个file.seek(0)呢,是因为符合我们的文件只有打开后才会发现编码不行,我们需要转换编码,那么此时这个文件已经是在open状态下的,但是这个文件已经被读了,所以这个文件的指针在最尾巴
这个时候我们脑子突发奇想
void Widget::on_CurrentIndexChanged(int index)//这个是设置编码的
{
ui->textEdit->clear();
if(file.isOpen()){
QTextStream in(&file);
in.setCodec(ui->comboBox->currentText().toStdString().c_str());
file.seek(0);
while(!in.atEnd()){
QString context = in.readLine();
// ui->textEdit->append(context);//追加到文本的末尾
ui->textEdit->setText(context);
}
}
}
用这个setText行不行?,但是我们会发现,我们的记事本的编码切换的时候第一行会被吃掉,为什么呢?这个跟setTest的特性有关
- setText():会覆盖 QTextEdit 中的现有内容。
- 循环逻辑:每次读取一行文本,然后用当前行覆盖之前的内容。
因此,只有最后一行会被保留,前面的行都会被后续迭代覆盖。
所以我们只能用这个append这个是用于追加的,这个只会追加到文本指针的后面,我们是每次读一行,那么就可以得出所有内容,因为都追加到前一行的末尾
file.seek(0);这个函数里面的参数是int类型的
QFileDevice::seek(qint64 pos) 是 Qt 中用于定位文件读写位置的核心函数,下面详细解释其参数和行为:
参数:qint64 pos
- 含义:要设置的文件位置(以字节为单位)。
- 类型:qint64(即long long,支持极大的文件大小)。
比如说:你好啊世界? 这个如果我们,设置seek(0)那么文件指针就到文件的最开始的位置
- ASCII 字符(英文字母、数字、符号):所有编码下都占 1 字节。
- 汉字:
- UTF-8:通常占 3 字节(范围 0xE0~0xEF 开头)。
- GBK/GB2312:占 2 字节(范围 0x81~0xFE 开头)。
- Unicode(UTF-16):固定 2 字节或 4 字节(取决于大端 / 小端)。
- 例:“饭” 在 UTF-8 中是 3 字节,在 GBK 中是 2 字节。
所以跟编码也有关系,但是这边我们记住这个seek(0)就是代表文件指针到此文件的开头
好的现在我们就是实现这个功能了