Qt开发经验小技巧271-275
- 编程的过程中经常遇到需要将QString转成char *或者const char *的情况,在转换成QByteArray后调用.data()或者.constData()函数进行转换,这里需要注意的是,如果转换类型是const char *尽管用data()不会出错,会给你自动转换,但是还是不建议,因为深拷贝了一份,理论上增加了内存开销,如果字符串长度小还好,一旦很长,这个开销挺大,这是个好的编程习惯。
//查阅代码得知data函数有两个重载
inline char *QByteArray::data()
{ detach(); return d->data(); }
inline const char *QByteArray::data() const
{ return d->data(); }
inline const char *QByteArray::constData() const
{ return d->data(); }
QByteArray data = "abc";
//深拷贝
char *d1 = data.data();
//深拷贝
const char *d2 = data.data();
//浅拷贝
const char *d3 = data.constData();
//深拷贝
test(data.data());
//浅拷贝
test(data.constData());
void test(const char *data)
{
}
//至于什么时候调用.data()会浅拷贝,酷码大佬说是当QByteArray被const修饰的时候
const QByteArray data;
//浅拷贝
const char *d = data.data();
//酷码大佬补充:自Qt 5.7版本以来,引入了qAsConst函数,专用于无脑转换。
//这个函数实现了C++17标准中的std::as_const()函数的功能,将一个非常量的左值转为常量的左值。
//增加qAsConst函数是为了Qt自己的非const 的容器能实现C++11标准的基于范围的循环。
//该函数主要用于qt容器在隐式共享中不被detach。
QString s = "abc";
//下面会深拷贝引起性能损失
for (QChar ch : s)
//不会深拷贝
for (QChar ch : qAsConst(s))
//下面也是浅拷贝,但是在编程时、在现实中,声明为const往往不容易做到。
const QString s;
for (QChar ch : s)
//总结:对Qt自己实现的容器如:QVector、QMap、 QHash、QLinkedList、QList等,如果一定要用基于for(var : container)范围的循环,则请用如下形式:
for (var : qAsConst(container))
新版的Qt6.5在ubuntu上编译运行程序后会提示 qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found. ,无法正常弹出窗体程序,你需要主动安装xcb的相关库。sudo apt install libxcb*
有些场景下我们需要在 QApplication a(argc, argv); 前面执行一些处理,比如 QApplication::setAttribute 就必须在最前面执行,而很多时候这个设置的参数不能改写死,毕竟现场的环境千差万别,希望通过配置文件来配置,那么问题来了,读取配置文件一般需要指定路径才能正常读取到,如果是 ./ 这种,很可能未必是应用程序的当前路径,如果你是双击运行的程序,那肯定是应用程序的当前路径,不是双击运行那就是系统环境中的当前路径,意味着你开机启动或者用system、QProcess等方式在开机后调用启动的话,就未必正确了。为了保证这个路径的正确,必须从main函数的 argv 第一个值获取,通过查阅Qt自身代码中获取路径,也是从这个参数获取。
//程序最前面获取应用程序路径和名称
static void getCurrentInfo(char *argv[], QString &path, QString &name);
//程序最前面读取配置文件节点的值
static QString getIniValue(const QString &fileName, const QString &key);
static QString getIniValue(char *argv[], const QString &key, const QString &dir = QString());
void QUIHelper::getCurrentInfo(char *argv[], QString &path, QString &name)
{
//必须用fromLocal8Bit保证中文路径正常
QString argv0 = QString::fromLocal8Bit(argv[0]);
QFileInfo file(argv0);
path = file.path();
name = file.baseName();
}
QString QUIHelper::getIniValue(const QString &fileName, const QString &key)
{
QString value;
QFile file(fileName);
if (file.open(QFile::ReadOnly | QFile::Text)) {
while (!file.atEnd()) {
QString line = file.readLine();
if (line.startsWith(key)) {
line = line.replace("\n", "");
line = line.trimmed();
value = line.split("=").last();
break;
}
}
}
return value;
}
QString QUIHelper::getIniValue(char *argv[], const QString &key, const QString &dir)
{
QString path, name;
QUIHelper::getCurrentInfo(argv, path, name);
QString fileName = QString("%1/%2%3.ini").arg(path).arg(dir).arg(name);
return getIniValue(fileName, key);
}
int main(int argc, char *argv[])
{
int openGLType = QUIHelper::getIniValue(argv, "OpenGLType").toInt();
QUIHelper::initOpenGL(openGLType);
QApplication a(argc, argv);
...
}
- 当我们对QTableView/QTreeView/QTableWidget/QTreeWidget某行选中后,会发现某些单元格设置的前景色被覆盖了,比如设置的红色,一旦选中就变成了白色,这肯定不是我们想要的,需要用自定义委托将其去掉。
class ItemDelegate : public QItemDelegate
{
Q_OBJECT
public:
explicit ItemDelegate(QObject *parent = 0);
protected:
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};
#include "itemdelegate.h"
ItemDelegate::ItemDelegate(QObject *parent) : QItemDelegate(parent)
{
}
void ItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItem option2 = option;
QColor color = index.data(Qt::ForegroundRole).value<QColor>();
if (color.isValid() && color != option.palette.color(QPalette::WindowText)) {
option2.palette.setColor(QPalette::HighlightedText, color);
}
QItemDelegate::paint(painter, option2, index);
}
//对所有单元格设置该委托
ui->tableWidget->setItemDelegate(new ItemDelegate);
- 有些时候我们需要在项目文件比如pro/pri中识别当前Qt套件是否存在某个模块以及是否引入过某个模块,存在则引入,同时也希望代码中也能识别是否引入过某个模块比如sql模块,判断后再进行对应的处理。
//项目文件中判断
//如果当前套件中有multimedia模块则引入multimedia模块
qtHaveModule(multimedia) {QT += multimedia}
//在项目文件中已经通过 QT += multimedia 引入过模块
contains(QT, multimedia) {}
//代码文件判断
#ifdef QT_MULTIMEDIA_LIB
qDebug() << "multimedia module is enabled";
#else
qDebug() << "multimedia module is not enabled";
#endif
国内站点:https://gitee.com/feiyangqingyun
国际站点:https://github.com/feiyangqingyun
Qt开发经验小技巧271-275的更多相关文章
- Qt开发经验小技巧81-90
Qt中的QColor对颜色封装的很完美,支持各种转换,比如rgb.hsb.cmy.hsl,对应的是toRgb.toHsv.toCmyk.toHsl,还支持透明度设置,颜色值还能转成16进制格式显示. ...
- Qt开发经验小技巧61-70
很多人问Qt嵌入式平台用哪个好,这里统一回答(当前时间节点2018年):imx6+335x比较稳定,性能高就用RK3288 RK3399,便宜的话就用全志H3,玩一玩可以用树莓派香橙派. 对于大段的注 ...
- Qt开发经验小技巧41-50
如果使用sqlite数据库不想产生数据库文件,可以创建内存数据库. QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); ...
- Qt开发经验小技巧71-80
在我们使用QList.QStringList.QByteArray等链表或者数组的过程中,如果只需要取值,而不是赋值,强烈建议使用 at() 取值而不是 [] 操作符,在官方书籍<C++ GUI ...
- Qt开发经验小技巧51-60
在某些http post数据的时候,如果采用的是&字符串连接的数据发送,中文解析乱码的话,需要将中文进行URL转码. QString content = "测试中文"; Q ...
- Qt开发经验小技巧31-40
代码判断MSVC编译器版本. if (_MSC_VER == 1800) MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015) MSVC++ 12.0 _ ...
- Qt开发经验小技巧21-30
如果出现Z-order assignment: is not a valid widget.错误提示,用记事本打开对应的ui文件,找到为空的地方,删除即可. 善于利用QComboBox的addItem ...
- Qt开发经验小技巧11-20
获取类的属性 const QMetaObject *metaobject = object->metaObject(); int count = metaobject->propertyC ...
- Qt开发经验小技巧1-10
当编译发现大量错误的时候,从第一个看起,一个一个的解决,不要急着去看下一个错误,往往后面的错误都是由于前面的错误引起的,第一个解决后很可能都解决了. 定时器是个好东西,学会好使用它,有时候用QTime ...
- Qt开发经验小技巧合集
一.开发经验总结 当编译发现大量错误的时候,从第一个看起,一个一个的解决,不要急着去看下一个错误,往往后面的错误都是由于前面的错误引起的,第一个解决后很可能都解决了. 定时器是个好东西,学会好使用它, ...
随机推荐
- ide 安装eval reset插件 Pycharm 永久破解
ide 安装eval reset插件 Pycharm 永久破解 1.安装eval reset的目的 Jetbrains家的产品有一个很良心的地方,他会允许你试用30天(这个数字写死在代码里了)以评估是 ...
- day06-Hello World案例
HelloWorld 象征着作为一个程序员向世界的第一声呐喊 新建一个文件夹用来存放代码 新建一个java文件 文件后缀名为.java Hello.java [注意]系统可能没有显示文件的后缀名,需要 ...
- MySQL数据的导出
有时需要将MySQL数据库中的数据导出到外部存储文件中,MySQL数据库中的数据可以导出成sql文本文件.xml文件或者html文件.本节将介绍数据导出的常用方法. 11.4.1 使用SELECT- ...
- Vmware挂载san存储_vSphere 6.x 共享存储LUN丢失分区表修复(精华)
Vmware挂载san存储_vSphere 6.x 共享存储LUN丢失分区表修复 炎炎夏夜客户机房空调意外故障,前端ESXI物理服务器由于温度过高都自保关机,存储和SAN没有自保关机.上班修复空调后, ...
- 新手入门使用pinia
.markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rg ...
- 鸿蒙 NEXT 如何使用 @Styles 装饰器来优化我的组件代码?
大家好,我是 V 哥.在鸿蒙 NEXT 开发中,@Styles 装饰器是一种非常有用的方法,用于定义可重用的样式.这使得开发者可以将多条样式设置提炼成一个方法,以便在多个组件中复用,从而提高代码的可维 ...
- PHP中$GLOBALS和global的区别,简单了解符号表、zval
前言 单位里有一套老代码,写了这么一个换库逻辑. function conn() { global $conn; if ($conn) { unset($conn); } $conn = mysqli ...
- 7000元才有的高性能显卡配置,ToDesk云电脑只要不到1块!
高性能显卡不仅仅是游戏玩家的刚需,也是设计师.工程师和剪辑师等专业人士的必备电脑配置.对于追求极致图形处理能力的用户来说,7000元的显卡预算并不罕见.然而,这样的花费对于大多数个人用户和小型企业来说 ...
- 狂神说-Docker基础-学习笔记-03 日志、元数据、进程的查看
狂神说-Docker基础-学习笔记-03 日志.元数据.进程的查看 视频链接:https://www.bilibili.com/video/BV1og4y1q7M4?p=1 1.docker logs ...
- uniswap v2 类比
当然,以下是生活中的类比,帮助你理解 Uniswap V2 的核心概念: 1. 自动化做市商(AMM) 生活中的例子:自动售货机 解释:自动售货机内部有一种商品(如饮料)和一定的库存.用户通过投币购买 ...