|回顾上一节
|继续拓展经验
211. 排列停靠窗口时,一些不常用的设置很容易被忘记。建议浏览一下头文件函数,以便更清楚地了解。
```cpp
//设置允许各种嵌套比如上下排列左右排列非常灵活
//此设置会和下面的 setDockOptions 中的参数覆盖所以要注意顺序
//this->setDockNestingEnabled(true);
//设置停靠参数,不允许重叠,只允许拖动和嵌套
this->setDockOptions(AnimatedDocks | AllowNestedDocks);
//将底部左侧作为左侧区域,底部右侧作为右侧区域,否则底部区域会填充拉伸
this->setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
this->setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
```
212.我们在检索数据时,常规字符(支持to的类型,比如toInt等)的数据可以轻松检索,而特定的数据类型则需要使用通用值模板函数T value()来检索。
```cpp
//显示文本
QString text = index.data(Qt::DisplayRole).toString();
//文本对齐
int align = index.data(Qt::TextAlignmentRole).toInt();
//文字字体
QFont font = index.data(Qt::FontRole).value
(); //前景色
QColor color = index.data(Qt::ForegroundRole).value
(); //背景色
QColor color = index.data(Qt::BackgroundRole).value
(); ```
213.很多人以为拖动可以在事件里进行,其实不然,这样不行,需要先在事件里执行event->(),不然根本没效果,很多人特别是初学者都是在这里失败的,我就是在这里摔倒的,好疼啊!
```cpp
void frmMain::dropEvent(QDropEvent *event)
{
QList
urls = event->mimeData()->urls(); }
void frmMain::dragEnterEvent(QDragEnterEvent *event)
{
if(event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist")) {
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
event->ignore();
}
}
```
214、Qt5.6 以后版本内置了浏览器内核,如果需要做网页交互,必须使用.js 文件,这个文件是 Qt 官方提供的,不建议改源码。需要注意的是,由于官方支持不断更新,官方对应的 Qt 版本的.js 文件也是不一样的,也就是说你要使用对应版本的.js 文件。该文件默认在 C:\Qt\Qt5.12.11\\Qt-5.12.11\\ 目录下。测试了几十个 Qt 版本,发现使用高版本的.js 在低版本上运行不行,低版本的在高版本上却能运行。为了保险起见,建议直接使用对应版本。
215. 删除空格的场景有很多,你可能需要删除左边的空格,右边的空格,或者所有位置的空格。
```cpp
//字符串去空格 -1=移除左侧空格 0=移除所有空格 1=移除右侧空格 2=移除首尾空格 3=首尾清除中间留一个空格
QString QtHelperData::trimmed(const QString &text, int type)
{
QString temp = text;
QString pattern;
if (type == -1) {
pattern = "^ +\\s*";
} else if (type == 0) {
pattern = "\\s";
//temp.replace(" ", "");
} else if (type == 1) {
pattern = "\\s* +$";
} else if (type == 2) {
temp = temp.trimmed();
} else if (type == 3) {
temp = temp.simplified();
}
//调用正则表达式移除空格
if (!pattern.isEmpty()) {
temp.remove(QRegularExpression(pattern));
temp.remove(QRegExp(pattern));
}
return temp;
}
//测试代码
QString text = " a b c d ";
//结果:a b c d
QtHelper::trimmed(text, -1);
//结果:abcd
QtHelper::trimmed(text, 0);
//结果:a b c d
QtHelper::trimmed(text, 1);
//结果:a b c d
QtHelper::trimmed(text, 2);
//结果:a b c d
QtHelper::trimmed(text, 3);
```
216、Qt 的网络库支持 udp 广播搜索和多播搜索,其中多播搜索可以跨网段搜索。有时候会发现失败,此时可以尝试禁用本地虚拟机的网卡,估计会修复。另外如果本地开启了代理,先尝试关闭。最近使用连接时发现在 Qt4、Qt5 中可以正常运行的程序在 Qt6 中无法正常运行,并报错“The proxy type is for this”。原来是本地代理设置导致的,可能是 Qt6 之前默认跳过了。
```cpp
//也可以通过代码设置跳过代理
QNetworkProxyFactory::setUseSystemConfiguration(false);
//下面这样每次设置也可以
tcpSocket->setProxy(QNetworkProxy::NoProxy);
//查阅到文章 https://www.cnblogs.com/cppskill/p/11730452.html
//从5.8开始socket默认代理类型是DefaultProxy而不是NoProxy,不知道出于什么考虑。
```
217.交叉编译对于初学者来说是一个非常难攻克的坎(攻克之后,以后再需要交叉编译的时候就易如反掌了),因为需要搭建一个交叉编译环境。好在现在厂商提供的板子基本都是经过测试好的环境,特别是提供的编译器,不用自己瞎折腾。按照官方手册来做基本不会有问题。
- 在Linux系统上编译和Qt是非常简单的任务,即使对于初学者来说也是如此,只要本地gcc g++编译器正常即可。
- 任何编译器,包括嵌入式编译器,为保证环境正常,可以先检查对应的编译器版本是否ok,g++ -v arm-linux-g++ -v。
- 检查交叉编译器版本 /opt///4.5.1/bin/arm-linux-g++ -v 。
- 编译器的位数和操作系统的位数有关,一般32位的编译器应该在32位系统上交叉编译,虽然32位的编译器在安装依赖包后可以在64位系统上交叉编译,但是个人不建议这样做,可能会出问题,64位的编译器只能在64位系统上使用。
- 如果设置了环境变量,可以省略长路径,直接输入可执行文件名;如果未设置环境变量,则需要输入完整路径。
- 设置环境变量只是为了在编译时自动找到编译器。事实上,你根本不需要设置环境变量,你可以使用绝对路径来指定编译器位置。
- 在Linux上编译,不管是Qt还是其他的,都是通用的步骤,第一步:./ 第二步:make 第三步:make。
- 至于具体参数,参考对应源码包的手册,搜索结果也很多,当然你也可以使用默认的,不加任何参数,会自动按照默认参数进行编译。
- 交叉编译命令:./ --=host --- --- ---doc --cross-=/opt///4.5.1/bin/arm-linux- --arch=arm ---os=linux
- 交叉编译qt前提条件:修改/qws/linux-arm-g++下的qmake.conf,如果没有设置环境变量,则设置对应编译器的绝对路径,并将编译器名称改为你需要的。
-例如修改gcc编译器:=/opt///4.5.1/bin/arm-linux-gcc
- 交叉编译 qt4.8.5 命令: ./ - host - arm - qws/linux-arm-g++ - - -- -qt-sql- -qt-gfx- --sql-sqlit -no- -no- -no-svg -no- -no--jit -no- -no- -no- -no--debug -qt-zlib -no-gif -qt- -qt- -no- -qt- -no -rpath -no-pch -no-3dnow -no-avx -no-neon -no- -no-nis -no-cups -no-dbus -- -qt- -no- -no-glib - demos - - docs - tools
- 交叉编译 qt5.9.8 命令: ./ - host - linux-arm-g++ --all - -- --qmake - -no--debug-info -strip - - -c++std c++1z -no-sse2 -pch -- -gui - -no-dbus -no- -no-cups -no- - -qt-zlib -qt- -qt- -qt-
- 总结一下,交叉编译和普通编译只有一个区别,就是需要手动指定交叉编译器的路径,这个是通过--cross-=来指定的。Qt比较大,所以需要改配置文件,最后通过--来指定配置文件名。
- Qt6的编译比较复杂,默认是用cmake编译的,在linux上,先使用.19以上版本的源码,用make编译生成cmake,再用cmake编译qt生成qmake,最后调用qmake编译你的qt项目。
- 编译Qt的时候只想用到库,至于demo,doc,tool等,都是用不到的,费时费力,所以强烈建议编译时去掉它们,这样可以大大加快编译速度。
- 建议用普通用户编译,包括解压源码,因为编译出来的库普通用户就可以使用,如果用root管理员编译的话,以后需要管理员权限。
- 很多系统提供直接右键解压,其实也可以,但是速度比较慢,建议使用命令行解压并删除目录。
- Qt 的编译参数可能每个版本都不一样,毕竟代码一直在更新,甚至一些分类描述也变了,比如-qt-xcb 在 5.15 改成了 -xcb,-qt-sql- 改成了 -qt-。大家一定要读源码,源码里规定了编译环境所需的最低版本,从 qt5 开始,具体的配置参数都放在目录下的描述里了。
- 编译后如果遇到GL/gl.h错误,需要安装apt -mesa-dev -mesa-dev或者yum mesa-libGL-devel mesa--devel。
- 编译参数的说明请参考[]()。
218. 有时候你可能会发现在 Qt 中设置图片会失败。这很可能是因为文件扩展名不正确。例如,jpg 的图片扩展名改成了 png,bmp 的图片扩展名改成了 jpg。当你传入文件路径加载图片时,会通过扩展名来调用相应的图片解析算法。这很笨,但很快,而且不需要分析具体的内部图片格式。如果想保证不管扩展名是什么都能加载成功,就必须读懂图片文件数据加载方法。
```cpp
//可以是资源文件中的图片也可以是本地文件
QString fileName = ":/test.png";
//此方式按照拓展名来区分具体格式不准确
//如果拓展名不正确就无法加载成功
ui->label->setPixmap(QPixmap(fileName));
//通过直接读取图片数据加载保证成功
QFile file(fileName);
file.open(QIODevice::ReadOnly);
QByteArray data = file.readAll();
//通过 QImage 处理
QImage img;
img.loadFromData(data);
//下面这种方式也行
//QImage img = QImage::fromData(data);
ui->label->setPixmap(QPixmap::fromImage(img));
//通过 QPixmap 处理
QPixmap pix;
pix.loadFromData(data);
ui->label->setPixmap(pix);
```
219. 总结一些关于 Qt 版本鲜为人知的事实。
- Qt4.8.7 是 Qt4 的最终版本,是 Qt4 系列中最稳定、最经典的版本(很多嵌入式板子还在用 Qt4.8)。其实这个版本和 Qt5.5 差不多是同时发布的。参考链接 []() []()
- Qt5.6.3是最后一个支持XP系统的长期支持版本,Qt5.7.0是最后一个支持XP系统的非长期支持版本(可能有极少数功能不受支持,但我个人没有遇到过)。
- Qt5.12.3为最后一个提供MySQL数据库插件的版本,后续版本需自行编译对应的MySQL数据库插件,官方不再提供安装包。
- Qt5.12.5是样式表性能最高的最后一个版本,酷码达人查看代码后发现,为了修复一个Bug,在后续版本的样式表源码中做了循环嵌套的设置,导致性能急剧下降,接口越多,性能下降10倍以上。
- Qt5.14.2是最后一个提供二进制安装包的版本,后续版本均需在线安装。
- Qt5.15系列是最后一个支持 7的版本,后续的Qt6系列版本需要更改源码编译才能支持 7,对于新手来说难度极大。
- Qt6.0/6.1版本其实也支持win7,但是因为缺少太多模块,而且bug太多,老板说连狗都不会用,所以用这个版本也没什么意义。
- Qt6 不支持 7,也就是说开发阶段和运行阶段都不支持,开发阶段和运行阶段都需要 Qt 库,只要 Qt 库不支持,任何地方都不会支持。
- 新版qtc7是用Qt6编译的,所以只能在 10以上版本运行。这意味着如果要使用新版qtc7+Qt5进行开发,也必须使用 10以上版本。
- 欢迎大家补充,比如哪个版本商业使用会收费? 好像用Qt4,不用改Qt本身的源代码,用动态库发布程序,法律风险会小一些?
220.除了Qt库不断升级,相应的集成开发环境也在不断更新升级,一般会使用最新的Qt库来编译新版本。需要注意的是,有些人安装了旧版本的qtc,却加载了高版本的Qt库,这样很容易出现ERROR: run 'g++'. Maybe you to setup the ?这样的错误信息。一般是版本跨度太大,比如使用Qt5.5自带的qtc加载Qt5.9的库,在某些环境下可能会识别不了,可能是新版本qtc改变了一些识别处理规则。所以一般建议使用新版qtc加载旧版Qt库,不建议使用旧版qtc加载新版Qt库。
221.在操作表格数据模型时,经常会遇到删除一条记录后,希望重新选择某一行的情况,支持多选和全选操作,例如批量删除等。
```cpp
//拿到表格数据模型
QAbstractItemModel *model = ui->tableView->model();
//主动定位到第三行
ui->tableView->setCurrentIndex(model->index(3, 0));
//主动定位到最后一行
ui->tableView->setCurrentIndex(model->index(model->rowCount() - 1, 0));
//设置选择模式支持多选,其他几个枚举值自行查阅文档。
ui->tableView->setSelectionMode(QAbstractItemView::MultiSelection);
//选择全部
ui->tableView->selectAll();
//取消所有选中
ui->tableView->clearSelection();
//选中行,注意如果该行选中则执行后取消选中,如此往复。这个设计很巧妙,掌声。
ui->tableView->selectRow(row);
//选中列,注意如果该列选中则执行后取消选中,如此往复。这个设计很巧妙,掌声。
ui->tableView->selectColumn(column);
//获取选中行的内容
QItemSelectionModel *selections = ui->tableView->selectionModel();
QModelIndexList selected = selections->selectedIndexes();
foreach (QModelIndex index, selected) {
qDebug() << index.row() << index.column() << index.data();
}
```
222、在读取文本文件的时候,有时候会发现读出来的汉字是乱码,这时候就需要识别一下文件的编码格式,然后主动设置相应的编码,就可以读出来不乱码了。
```cpp
//检查文件编码 0=ANSI 1=UTF-16LE 2=UTF-16BE 3=UTF-8 4=UTF-8BOM
int DataCsv::findCode(const QString &fileName)
{
//假定默认编码utf8
int code = 3;
QFile file(fileName);
if (file.open(QIODevice::ReadOnly)) {
//读取3字节用于判断
QByteArray buffer = file.read(3);
quint8 b1 = buffer.at(0);
quint8 b2 = buffer.at(1);
quint8 b3 = buffer.at(2);
if (b1 == 0xFF && b2 == 0xFE) {
code = 1;
} else if (b1 == 0xFE && b2 == 0xFF) {
code = 2;
} else if (b1 == 0xEF && b2 == 0xBB && b3 == 0xBF) {
code = 4;
} else {
//尝试用utf8转换,如果可用字符数大于0,则表示是ansi编码
QTextCodec::ConverterState state;
QTextCodec *codec = QTextCodec::codecForName("utf-8");
codec->toUnicode(buffer.constData(), buffer.size(), &state);
if (state.invalidChars > 0) {
code = 0;
}
}
file.close();
}
return code;
}
```
223、连接远程数据库查询数据时,有时可能会发现很慢,特别是表中的数据越多越慢。如果是本地,同样数量的数据就快得多。可以尝试启用-only属性query.(true);这样只会缓存一次数据,大大提高远程数据库的查询效率,据说可以提高几十倍、几百倍的速度。当然前提是需要在查询的数据之前向前取数据,如果需要向后取数据或者在数据模型中使用,就不能启用这个属性。原因是每次使用它来获取下一条记录时,如果不启用该属性(很遗憾,默认情况下不启用),每次都会开辟一块新的内存空间来存储已经访问过的和未访问过的记录。这样每次都会浪费大量的存储空间。
224.Qt中的绘图非常灵活和强大,接口丰富,但对于很多初学者来说还是比较难的,特别是各种奇怪和复杂的格式。这些格式用HTML来描述非常容易,比如控制行距,字符间距等。这时就可以传入HTML格式的内容进行绘图,非常完美,简单而强大,包括一些数学公式。
```cpp
void Form::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
QTextDocument doc;
doc.setHtml(html);
//设置文本宽度
doc.setTextWidth(200);
//指定绘制区域
doc.drawContents(&painter, QRect(0, 0, 200, 70));
}
```
225.在Qt中,样式表对于选中状态颜色和悬停状态颜色是有优先级的。根据对操作系统默认样式的观察,当处于选中状态+悬停状态时,默认为悬停状态,即鼠标移动到选中列表项上时,颜色为悬停状态颜色。如果在Qt中两种颜色都设置了,则按照设置的顺序使用最后一种。如果设置了最后一种选中状态颜色,当项处于选中状态+悬停状态时,则使用选中状态颜色,而不是悬停状态颜色。切记!
```cpp
//下面这样设置则当鼠标停留在选中的item上时背景颜色=#00FF00
QTableView::item:selected{background:#FF0000;}
QTableView::item:hover{background:#00FF00;}
//下面这样设置则当鼠标停留在选中的item上时背景颜色=#FF0000
QTableView::item:hover{background:#00FF00;}
QTableView::item:selected{background:#FF0000;}
//左上角样式很容易忽略
QTableCornerButton:section{background:#FF0000;}
```
226. qtc开发工具内置了不少的函数,可以很方便的进行一些判断和处理。
```cpp
//最小版本要求
!minQtVersion(5, 15, 2) {
message("Cannot build Qt Installer Framework with Qt version $${QT_VERSION}.")
error("Use at least Qt 5.15.2.")
}
```
227、有时文本框中的内容过长,文本框默认光标在最后,需要主动设置光标移动到最前面
```cpp
//三种方法都可以
ui->lineEdit->setSelection(0, 0);
ui->lineEdit->setCursorPosition(0);
//样式表方式
"QLineEdit{qproperty-cursorPosition:0;}
```
228. 关于 Qt 浏览器模块的几点说明。
- Qt5.6之前,Qt5.6之后有两种情况,一种是mingw编译器(系统)对应的Qt库不再提供浏览器模块。
- Qt5.6之后的版本在Linux和Mac系统上没有浏览器控件,全部使用它。
- 只有系统上的mingw编译器的Qt版本没有,其他系统居然都有。很多人对此抱有怀疑,都以为只有msvc编译器才有浏览器控件。其实准确的说,msvc上的Qt库才有浏览器控件。
- 安装Qt时,默认不勾选该模块,需要主动勾选才会安装。
- msvc Qt 不是所有版本都有浏览器模块,即使查了也没有,有些版本不是官方编译的,需要自己编译,需要到对应Qt安装目录下查看是否有.dll文件。
- 如果只是为了弥补mingw版本缺少浏览器模块的遗憾,还是推荐的。
- 如果想要兼容各个版本和系统,建议使用cef。
- 如果没有历史包袱,建议使用,因为它和Qt集成度很高。
- 都不支持 GPU,默认使用 GPU。
- 默认不支持MP4,需要自行重新编译。
229.编写数据库插件的几点经验总结。
- 安装对应的数据库。安装完之后会有头文件和lib链接库文件,这个是基本前提,这两个东西是编译数据库插件必须的,请注意32位的Qt一定要安装32位的数据库才能编译成功,位数要一致。
- 准备好数据库插件源码,例如qt--src-5.14.2\\src\\\mysql,可以在安装Qt的时候查看src,也可以直接在官网下载源码然后稍后解压。
- 打开要编译的数据库插件的源代码,例如对于MySQL,打开mysql.pro,对于oci.pro。
- 在 pro 中注释掉 # += mysql 行,如果是 oci 项目,则注释掉 # += oci 行。
- 注释掉 .pri 文件中的 #(..(..PWD)/-.pri)。
- 在mysql.pro文件内容下方添加以下代码。
```cpp
路径 = C:/Qt/mysql-5.7.30-
+= $$路径/
win32:LIBS + = -L$$path/lib-
```
- 在oci.pro文件内容下方添加以下代码。
```cpp
路径 = C:/app///11.2.0/
+= $$路径/oci/
win32:LIBS + = -L$$path/oci/lib/msvc -loci
```
- 在psql.pro文件内容下方添加以下代码。
```cpp
路径 = “C:/Files//13”
+= $$路径/
win32:LIBS + = -L$$path/lib-
```
- 以上写法同时支持mingw和msvc,其他系统的编译过程类似。编译完成后默认会在你当前源代码所在的驱动器根目录下出现一个目录,目录下就有对应编译好的插件动态库。
- 默认的插件驱动代码是按照功能写的,如果链接的话需要改两行代码才能编译成功,打开.cpp文件,大概1559行代码,有一个函数改成,下面还有一行改成(ub2*)。
230. 有关 Qt 数据库开发的一些鲜为人知的事实。
- Qt支持以库的形式直接与数据库通讯,同时也支持以ODBC数据源的形式与各种数据库通讯,从而覆盖了所有情况。
- Qt数据库程序打包发布。全部必备:注意区分32/64位,如果你的程序是32位的,就必须带32位的库,如果是64位的,就必须带64位的库,这也是Qt对库的要求。MySQL最容易发布,只要带mysql动态库文件(.dll)就行,很简单,不用带,因为是微软自家儿子,一般操作系统内置了,只需要带libpq.dll、-8.dll、-2.dll、.dll、.dll即可。oci.dll和.dll需要带(这个文件很大,130MB+)。如果还是不行,建议直接装一个客户端软件,然后把对应的bin目录设置到环境变量中。
- 打包发布后我们测试发现32位程序也能正常连接64位mysql,64位程序也能正常连接32位mysql。所以只要程序库位数一致即可(编译时也是同样的规则,32位Qt程序编译数据库插件,也需要使用32位的数据库链接库),不需要和具体数据库位数一致。经过mysql、数据库的测试,都是类似的规则。
- 经过大量的测试和比较,通过ODBC数据源方法和直接连接数据库方法批量插入大量数据记录速度更快,大约快5%,所以建议尽量使用此方法。ODBC数据源方法只在无法使用此方法的环境中使用。Qt默认自带了ODBC数据库插件。
- 不同的数据库在执行sql脚本时会自动将表名或字段名转换为大写或小写。MySQL会将表名转换为小写,表名和字段名转换为小写,表名和字段名转换为大写。这意味着当你使用调用设置数据库表名时,必须与数据库中的表名一致,并且区分大小写。所以在匹配数据库时一定要注意。我在这里卡了好久,差点把这个巨大的坑归咎于Qt的BUG。
```cpp
void DbHelper::bindTable(const QString &dbType, QSqlTableModel *model, const QString &table)
{
//postgresql全部小写,oracle全部大写,这两个数据库严格区分表名字段名的大小写卧槽
QString flag = dbType.toUpper();
if (flag == "POSTGRESQL") {
model->setTable(table.toLower());
} else if (flag == "ORACLE") {
model->setTable(table.toUpper());
} else {
model->setTable(table);
}
}
```
- Qt支持打开数据库时不指定数据库名,因为有时候连接数据库服务器后需要执行SQL语句创建数据库。如果数据库还不存在怎么连接呢?测试发现mysql、、都支持这个特性。删除、创建数据库的前提是数据库没有被其他程序占用,比如其他程序已经打开了数据库,那么执行就会失败。我在这里被折磨过很多次,为什么会执行失败呢?后来发现是第三方数据库工具已经打开了数据库,关闭工具就没事了。
```cpp
QSqlDatabase database = QSqlDatabase::addDatabase("QMYSQL");
//database.setDatabaseName("dbtool");
database.setHostName("127.0.0.1");
database.setPort(3306);
database.setUserName("root");
database.setPassword("root");
if (database.open()) {
QSqlQuery query(database);
qDebug() << "删除数据库" << query.exec("drop database dbtool");
qDebug() << "创建数据库" << query.exec("create database dbtool");
if (query.exec("select * from userinfo")) {
while (query.next()) {
qDebug() << "查询数据库" << query.value(0);
}
}
} else {
qDebug() << "打开数据库" << database.lastError().text();
}
```
- 使用 + 显示数据,如果 int 型数据超过 100 万,就会以科学计数法显示,很烦人,肯定不是你想要的结果。在网上找了好久,终于找到一个哥们有同样的问题,他只要给这个列加一个空的 就行了。后来发现空的 不管用,如果超过 1000 万,那就太牛逼了,需要终极方法,重新加载数据模型才能显示。
```cpp
ui->tableView->setItemDelegateForColumn(0, new QItemDelegate);
//下面是终极大法
QVariant SqlQueryModel::data(const QModelIndex &index, int role) const
{
QVariant value = QSqlQueryModel::data(index, role);
//超过100万的数值会被科学计数显示需要这里转成字符串显示
if (role == Qt::DisplayRole) {
int result = value.toInt();
if (result >= 1000000) {
value = QString::number(result);
}
}
return value
}
```
- MySQL数据库有多个数据库引擎,有些不支持数据库事务,一般默认就用这个引擎。所以使用Qt的方法提交时会发现不成功,其实是成功的,去数据库里查看对应结果是正确的。有两种方法,第一种是换数据库引擎,第二种是提交后做错误判断 if (mit() || !.().()),错误没有,也代表成功了。
- 如果使用ODBC数据源通讯,则只需要设置数据库名称、用户名、用户密码即可。因为在配置数据源的时候已经设置了对应的主机地址和端口以及关联的数据库名称,所以在使用ODBC数据源通讯时,只需要再次验证用户信息即可。需要注意的是,设置数据库名称时,必须填写数据源中配置的名称。
- 经过大量对比测试,包括插入、删除、批量、查询、分页等操作,千万级数据,Qt数据库响应速度友好度排名为>> > mysql > odbc。千万级以上为>> mysql >> odbc。亿级以上为>> 其他。以上测试均基于初学者水平,并未用到分片、联合查询、缓存、内存数据库等各种高级知识点。
- MySQL 主要有两个版本,分别是 .7 和 . 官方给出的版本是 8 比 5 快很多,从我个人的测试来看,5.7 比 8 快很多,不管是查询还是批量插入数据。不知道为什么,网上查的结果都是一样的([]()),大家都说 8 慢很多。
- MySQL 有个分支叫 ,比 MySQL 更纯粹,据说各方面都比 MySQL([]()) 强。我个人对比测试,批量插入、查询性能确实好很多,而且完全兼容 MySQL。甚至库文件都可以直接改名直接使用,比如把 .dll 改成 .dll 就可以直接使用。而且体积小了八倍,不错,发布的时候可以省好几兆。
- 如果是Qt+mysql程序,发布时包含的库版本必须与插件对应的数据库版本一致,否则可能没有数据库事务特性且.()->(::)会为false。
- 封装的非常好,并不是一次性加载所有数据,而是随着滚动条的拉动,加载需要的数据。在测试一个亿记录的表时,速度非常快,和几千条记录的表速度一样。
- 在连接网络数据库的时候,如果你的本地网络设置了代理,比如使用代理访问网站,你会发现Qt的数据库程序无法连接。你需要设置成不使用本地代理设置::ation(false)。这个地方如果不仔细看,你会发现问题多到怀疑人生。