简单了解编码:
latin1(ISO 8859-1)字符集是对ASCII基本字符集的扩展,都是1字节编码。
Unicode编码有多重存储方案,utf-8使用1~4字节编码,最少1字节;utf-16使用2-4字节编码,最少2字节。
主要练习Qchar,QString,Qstring和数值的转换,以及资源文件的加载和显示居中处理。
QChar主要练习一下unicode编码,和ASCII字符串编码c字符的转换。
QString字符串主要练习不同编码形式的初始化,除了静态直接初始化,也有对应成员初始化,以及常用的成员函数。
加载资源文件,spinbox控件练习,文本控制居中练习。
1:QChar练习
1.1 主要关注QChar的字符编码,初始化,以及和正常字符的转换。
//简单整理Qchar相关知识 QChar占两个字节,主要表示unicode字符,需要知道ascii,ISO-8859-1 (Latin1) 和uncode字符之间的转换
//其他的QChar相关静态函数和成员函数都是基础使用 比较,判空白字符,转大小写,数字字母等
void Widget::on_pbn_qchar_clicked()
{
//首先是基础的QChar的用法练习,初始化可以参考构造函数
//QChar类表示一个Unicode字符, 即可以存汉字, 占用字节大小也可以
QString str = "hello, 北京";
// QChar dst0('青'); //高版本的应该可以这样初始化
QString dst = "青岛";
QChar dst0 = dst[0];
QChar dst1 = dst[1].unicode(); //可以直接用对应的unicode初始化 比如dst[1].unicode()
ui->pte_Display->setPlainText(dst +QString::asprintf("\t对应的Unicode编码 = 0x%X 0x%X。", dst0.unicode(), dst1.unicode()));
//验证Qchar占用两个字节,但是实际上转成unicode字符,汉字才是两个字节
for(short int i=0; i<str.size(); i++)
{
QChar ch = str.at(i);
char16_t unicode = ch.unicode(); //获取QChar字符的UTF-16编码值
ui->pte_Display->appendPlainText(QString(ch)+"\t大小:"+QString::number(sizeof (ch))+QString::asprintf("\tunicode编码:0x%X",unicode));
}
//QChar使用utf-16处理字符,可以标识unicode字符,练习字符之间的转换
QChar chP = QChar::fromLatin1('P'); //Latin1:ISO-8859-1 8位扩展的ASCII
// QChar chTest = QChar::fromUcs2(0x5C9B); //'岛' qt6的版本可用?
ui->pte_Display->appendPlainText("QChar \""+QString(chP)+"\"转成ASCII字符:"+QChar(chP.toLatin1()));
}
1.2:demo运行结果
2:QString联系
2.1 :QString的不同初始化
void Widget::on_pbn_qstring_clicked()
{
//涉及不同的编码,所以这里简单了解一下QString不同编码的初始化方式,然后都有对应的转换方法
QString str = "";
//fromCFString 没了解过CFStringRef 不考虑
//fromLocal8Bit 是本地Gb字符集转unicode QString默认是Unicode
//主要用于外部传入的文件 字符数组 这里一般提前知道对应字符的编码方式
QString src_str = "你好";
QByteArray data_qbytearr = src_str.toLocal8Bit();
QString str_qbytearr = QString::fromLocal8Bit(data_qbytearr);
QString str_char = QString::fromLocal8Bit(data_qbytearr.data(), data_qbytearr.size());
ui->pte_Display->setPlainText("fromLocal8Bit QByteArray转qstring:"+str_qbytearr);
ui->pte_Display->appendPlainText("fromLocal8Bit str_char转qstring:"+str_char);
QString src_str1 = "你好";
char data_char[20] = {0}; //这里本来想直接用char* 发现有异常
memcpy(data_char, src_str1.toLocal8Bit().data(), strlen(src_str1.toLocal8Bit().data()));
str_char = QString::fromLocal8Bit(data_char, strlen(data_char));
ui->pte_Display->appendPlainText("fromLocal8Bit str_char转qstring:"+str_char);
//fromLatin1 主要就是字符到QString的转换了 我的理解是一般就是我们理解的ASCII
data_qbytearr.clear();
data_qbytearr.push_back("hello,world;");
str_qbytearr = QString::fromLatin1(data_qbytearr); //反转可以用
std::string str_std = str_qbytearr.toLatin1().toStdString();
ui->pte_Display->appendPlainText("QString转std::string:"+QString(str_std.c_str()));
str_char = QString::fromLatin1(data_qbytearr.data(),data_qbytearr.size());
ui->pte_Display->appendPlainText("fromLatin1 QByteArray转qstring:"+str_qbytearr);
ui->pte_Display->appendPlainText("fromLatin1 str_char转qstring:"+str_char);
//fromNSString 是其他平台上的接口
//fromRawData 这个用法感觉用不到 参考手册demo了
static QChar std_unicode[] = { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x9752, 0x5c9b};//Hello,青岛
int size = sizeof(std_unicode) / sizeof(QChar);
QString qstr_dst = QString::fromRawData(std_unicode, size);
ui->pte_Display->appendPlainText("fromRawData QChar*转qstring:"+qstr_dst +"size:"+QString::number(size));
//打印地址的练习
qDebug()<<"addr :"<<qPrintable(qstr_dst); //qPrintable 将QString转换成char*字符串而已
qDebug("Address of QChar array: %p", qstr_dst.data());
qDebug("Address of QChar array: %p", reinterpret_cast<void*>(std_unicode));
std_unicode[0] = 0x9752;//如果修改了Qchar中的值 QString中并未改变
ui->pte_Display->appendPlainText("fromRawData QChar*转qstring:"+qstr_dst +"size:"+QString::number(size));
const char* std_str_test = "test std::string";
ui->pte_Display->appendPlainText("fromStdString std::string转qstring:"+QString::fromStdString(std_str_test));
std::u16string u16str = u"Hello, 世界";
ui->pte_Display->appendPlainText("fromStdU16String std::u16string转qstring:"+QString::fromStdU16String(u16str));
std::u32string u32str = U"Hello, 世界";
ui->pte_Display->appendPlainText("fromStdU32String std::u32string转qstring:"+QString::fromStdU32String(u32str));
std::wstring wstr = L"Hello, 世界";
ui->pte_Display->appendPlainText("fromStdWString std::wstring转qstring:"+QString::fromStdWString(wstr));
//UTF-32
unsigned int ucs4[] = {0x0048, 0x0065, 0x006c, 0x006c, 0x006f,
0x002c, 0x0020, 0x4e16, 0x754c}; // "Hello, 世界" in UCS-4
ui->pte_Display->appendPlainText("fromUcs4 utf-32转qstring:"+QString::fromUcs4(ucs4, sizeof(ucs4) / sizeof(unsigned int)));
const char* utf8char = "\xe4\xbd\xa0\xe5\xa5\xbd"; // UTF-8编码的字符串 你好
ui->pte_Display->appendPlainText("fromUtf8 utf-8转qstring:"+QString::fromUtf8(utf8char, strlen(utf8char)));
const char16_t * utf16char = u"你好";
int u16size = 0;
while (utf16char[u16size] != u'\0') {
++u16size;
}
ui->pte_Display->appendPlainText("fromUtf16 utf-16转qstring:"+QString::fromUtf16(utf16char, u16size));
wchar_t* wideStr = L"Hello, 你好!"; // 宽字符字符串
// QString dst111;
// dst111.toWCharArray(wideStr); //成员函数也可以
ui->pte_Display->appendPlainText("fromWCharArray wchar_t转qstring:"+QString::fromWCharArray(wideStr, wcslen(wideStr)));
//字符串比较 localeAwareCompare
qstrFunc();
}
2.2:常用接口练习
contains包含,fill填充, push_back,push_front,prepend,insert插入,replace修改,chop删空格,QStringRef只读引用
//简单字符串操作函数整理
void Widget::qstrFunc()
{
QString qstr = "hello, world! 主要测试qString的一些常用函数。";
QString qstr_st = "hello, world!";
QString qstr_ed = "函数。";
if(qstr.contains(qstr_st)) //第二个参数大小写敏感或者不敏感,以及其他的重载函数可以研究
{
ui->pte_Display->appendPlainText(qstr +"中包含字符串:"+qstr_st);
}
if(!qstr_st.contains(qstr_ed)) //第二个参数大小写敏感或者不敏感,以及其他的重载函数可以研究
{
ui->pte_Display->appendPlainText(qstr_st +"中不包含字符串:"+qstr_ed);
}
ui->pte_Display->appendPlainText(qstr_st +"字符串个数:"+QString::number(qstr_st.count()));
ui->pte_Display->appendPlainText("endsWith测试:"+ QString((qstr.endsWith(qstr_ed))?"true":"false"));
ui->pte_Display->appendPlainText("startsWith测试:"+ QString((qstr.startsWith(qstr_st))?"true":"false"));
QString qstr_fill;
qstr_fill.fill(QChar('P'), 5);
ui->pte_Display->appendPlainText("fill填充测试:"+ qstr_fill);
qstr_fill = "PXYZE";
ui->pte_Display->appendPlainText(qstr_fill+"字符串front 测试:"+ qstr_fill.front());
ui->pte_Display->appendPlainText(qstr_fill+"字符串back 测试:"+ qstr_fill.back());
if(qstr_fill.front() == QChar('P'))
{
qstr_fill.remove(0,1);
}
ui->pte_Display->appendPlainText(qstr_fill+"字符串remove 测试:"+ qstr_fill);
qstr_fill.push_back('D');
qstr_fill.prepend("prepend");
qstr_fill.push_front("F");
qstr_fill.insert(0, "Insert"); //简单测试,可以参考对应重载函数
qstr_fill.replace(0,3,"res");
ui->pte_Display->appendPlainText("字符串插入测试:"+ qstr_fill);
ui->pte_Display->appendPlainText(qstr_fill+"字符串indexof(prepend)测试:"+ QString::number(qstr_fill.indexOf("prepend")));
ui->pte_Display->appendPlainText(qstr_fill+"字符串lastIndexOf(prepend)测试:"+ QString::number(qstr_fill.lastIndexOf("prepend")));
ui->pte_Display->appendPlainText(qstr_fill+"字符串对齐测试:"+ qstr_fill.leftJustified(8, '_'));
ui->pte_Display->appendPlainText(qstr_fill+"字符串left截断字符测试:"+ qstr_fill.left(5));
ui->pte_Display->appendPlainText(qstr_fill+"字符串right截断测试:"+ qstr_fill.right(5));
QString qstr_simplified= " hello, my test! ";
ui->pte_Display->appendPlainText(qstr_simplified+"字符串去除 头尾空格并合并多个空格测试:"+ qstr_simplified.simplified());
ui->pte_Display->appendPlainText(qstr_simplified+"长度:"+ QString::number(qstr_simplified.size())
+" "+QString::number(qstr_simplified.capacity())+QString::number(qstr_simplified.count()));
qstr_simplified.shrink_to_fit(); //压缩空间 在QString中好像没啥用
ui->pte_Display->appendPlainText(qstr_simplified+"压缩后长度:"+ QString::number(qstr_simplified.size())
+" "+QString::number(qstr_simplified.capacity())+QString::number(qstr_simplified.count()));
qstr_simplified = "hello,mytest!";
qstr_simplified.chop(2); //移出最后两个字符
ui->pte_Display->appendPlainText(qstr_simplified+"字符串chop去除最后两个字符测试:"+ qstr_simplified
+" chopped 测试:"+qstr_simplified.chopped(2) );
qstr_simplified.replace(0,3,"DDDD");//从0开始3个字符替换为DDDD 可以参考其他重载函数
ui->pte_Display->appendPlainText(qstr_simplified+"字符串 replace测试:"+ qstr_simplified);
//left right 以及引用测试
qstr_simplified = "hello,mytest!";
ui->pte_Display->appendPlainText(qstr_simplified+"字符串 left测试:"+ qstr_simplified.left(5));
ui->pte_Display->appendPlainText(qstr_simplified+"字符串 right测试:"+ qstr_simplified.right(5));
QStringRef qstr_ref = qstr_simplified.midRef(3, 4);
QStringRef qstr_ref1 = qstr_simplified.rightRef(5);
QStringRef qstr_ref2 = qstr_simplified.leftRef(5);
ui->pte_Display->appendPlainText(qstr_simplified+"字符串 引用测试:"+qstr_ref +" "+ qstr_ref1 +" "+qstr_ref2);
//QStringRef 是QString的只读引用 使用时确保源QString不会变
qstr_simplified.replace(qstr_simplified.size()-3, 2, "OO");
ui->pte_Display->appendPlainText("字符串 引用测试:"+ qstr_simplified + " "+qstr_ref1); //引用也发生 变化了
}
2.3:demo运行结果
2.4:QString和数值之间的转换
和整数十进制,二进制,十六进制的转换;
和浮点数的转换,以及设置位数。
以及arg成员函数,asprintf,vasprintf
//为测试vasprintf 构造对应的参数 va_list
QString fun(char* msg,...){
va_list ap;
va_start(ap, msg);
QString buf = QString::vasprintf(msg, ap);
va_end(ap);
return buf;
}
//简单整理QString和数值转换相关知识
void Widget::on_pbn_strnum_clicked()
{
QString qstr = QString::asprintf("asprintf 测试:%d %s.", 2, "test");
ui->pte_Display->setPlainText("asprintf测试:"+qstr);
char fmt[] = "vasprintf 测试:%d %s.";
ui->pte_Display->appendPlainText("vasprintf测试:"+fun(fmt, 2,"test"));
ui->pte_Display->appendPlainText("arg测试:"+QString("arg 测试 %1 %2 %3").arg(int(1)).arg(ushort(2)).arg(QString("test")));
// qstr.squeeze(); //QString用不到 释放不用内存
qstr = "hello,test!";
QString qstr_swap;
qstr_swap.swap(qstr);
ui->pte_Display->appendPlainText("swap测试: src:"+qstr+" dst:"+qstr_swap);
qstr.resize(5, 'A');
ui->pte_Display->appendPlainText("resize测试: "+qstr +" size:"
+QString::number(qstr.size())+" "+QString::number(qstr.capacity())
+" "+QString::number(qstr.length()));
qstr.reserve(10);
ui->pte_Display->appendPlainText("reserve测试: "+qstr+" size:"
+QString::number(qstr.size())+" "+QString::number(qstr.capacity())
+" "+QString::number(qstr.length()));
ui->pte_Display->appendPlainText("isEmpty测试: "+QString(qstr.isEmpty()?"true":"false"));
ui->pte_Display->appendPlainText("isNull测试: "+QString(qstr.isNull()?"true":"false"));
ui->pte_Display->appendPlainText("isLower测试: "+QString(qstr.isLower()?"true":"false"));
ui->pte_Display->appendPlainText("isUpper测试: "+QString(qstr.isUpper()?"true":"false"));
ui->pte_Display->appendPlainText("isRightToLeft测试: "+QString(qstr.isRightToLeft()?"true":"false"));
//简单测试一下迭代器遍历
QString::const_iterator itr = qstr.begin();
while(itr!=qstr.end())
{
qDebug()<<"qstr:"<<*itr;
++itr;
}
//字符串和数值的转换 setnum 或者arg QString::number asprintf vasprintf
QString qstr_num;
int int_num = 0;
bool ok = false;
qstr_num.setNum(18, 10);
ui->pte_Display->appendPlainText("setNum 十进制测试: "+qstr_num);
int_num = qstr_num.toInt(&ok);
ui->pte_Display->appendPlainText("toInt 十进制测试: "+QString::number(int_num));
qstr_num.setNum(18, 2);
ui->pte_Display->appendPlainText("setNum 二进制测试: "+qstr_num);
int_num = qstr_num.toInt(&ok,2);
ui->pte_Display->appendPlainText("toInt 二进制测试: "+QString::number(int_num));
qstr_num.setNum(18, 16);
ui->pte_Display->appendPlainText("setNum 十六进制测试: "+qstr_num);
int_num = qstr_num.toInt(&ok, 16);
ui->pte_Display->appendPlainText("toInt 十六进制测试: "+QString::number(int_num));
//setnum处理浮点数
double num= 1245.2783;
qstr_num.setNum(num,'f',5); //小数点后5位, str= "1245.27830"
ui->pte_Display->appendPlainText("setNum 浮点数小数点后5位测试: "+qstr_num);
qstr_num.setNum(num,'E',5);
ui->pte_Display->appendPlainText("setNum 浮点数小数点后5位测试: "+qstr_num);
qstr_num.setNum(num,'g',5);
ui->pte_Display->appendPlainText("setNum 整数小数共5位测试: "+qstr_num);
qstr_num.setNum(num,'g',3);
ui->pte_Display->appendPlainText("setNum 整数小数共3位测试: "+qstr_num);
//字符串转数值
float float_num = qstr_num.toFloat(&ok);
ui->pte_Display->appendPlainText("toFloat 字符串转浮点数测试: "+QString::number(float_num));
//其他
static QChar std_unicode[] = { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x9752, 0x5c9b};//Hello,青岛
int size = sizeof(std_unicode) / sizeof(QChar);
qstr_num.setRawData(std_unicode, size);
ui->pte_Display->appendPlainText("setRawData 测试: "+qstr_num);
qstr_num.setUnicode(qstr.unicode(), qstr.size());
ui->pte_Display->appendPlainText("setUnicode 测试: "+qstr_num);
const ushort utf16char[] = {0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x0020, 0x0057, 0x006F, 0x0072, 0x006C,
0x0064, 0};
int u16size = 0;
while (utf16char[u16size] != u'\0') {
++u16size;
}
ushort *data1 = const_cast<ushort*>(utf16char);
qstr_num.setUtf16(data1, u16size);
ui->pte_Display->appendPlainText("setUtf16 测试: "+qstr_num);
}
2.5:demo运行结果(居中显示)
3:spinbox的练习
3.1:简单练习数值转换:
void Widget::init()
{
//这里spinbox相关设置字体 长宽 等各种函数可以探索
ui->spinbox_bin->setStepType(QAbstractSpinBox::AdaptiveDecimalStepType); //自适应步长
ui->spinbox_bin->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed); //水平扩展,垂直固定
ui->spinbox_bin->setRange(0, 65535);
ui->spinbox_dec->setRange(0, 65535);
ui->spinbox_hex->setRange(0, 65535);
ui->spinbox_bin->setDisplayIntegerBase(2);
ui->spinbox_dec->setDisplayIntegerBase(10);
ui->spinbox_hex->setDisplayIntegerBase(16);
ui->spinbox_dec->setValue(10);
}
void Widget::on_spinbox_hex_valueChanged(int arg1)
{
ui->spinbox_bin->setValue(arg1);
ui->spinbox_dec->setValue(arg1);
}
3.2:demo运行结果
4:处理居左,居中,居右显示
void Widget::on_pbn_left_clicked()
{
ui->spinbox_bin->setAlignment(Qt::AlignLeft);
//使用时Qt版本比较低 qt6可以用setAlignment吧
QTextDocument *doc = ui->pte_Display->document();
doc->setDefaultTextOption(QTextOption(Qt::AlignLeft));
ui->pte_Display->setDocument(doc);
}
void Widget::on_pbn_center_clicked()
{
ui->spinbox_bin->setAlignment(Qt::AlignCenter);
QTextDocument *doc = ui->pte_Display->document();
doc->setDefaultTextOption(QTextOption(Qt::AlignCenter));
ui->pte_Display->setDocument(doc);
}
void Widget::on_pbn_right_clicked()
{
ui->spinbox_bin->setAlignment(Qt::AlignRight);
QTextDocument *doc = ui->pte_Display->document();
doc->setDefaultTextOption(QTextOption(Qt::AlignRight));
ui->pte_Display->setDocument(doc);
}