- 編程的過程中經(jīng)常遇到需要將QString轉(zhuǎn)成char *或者const char *的情況,在轉(zhuǎn)換成QByteArray后調(diào)用.data()或者.constData()函數(shù)進(jìn)行轉(zhuǎn)換,這里需要注意的是,如果轉(zhuǎn)換類型是const char *盡管用data()不會(huì)出錯(cuò),會(huì)給你自動(dòng)轉(zhuǎn)換,但是還是不建議,因?yàn)樯羁截惲艘环荩碚撋显黾恿藘?nèi)存開銷,如果字符串長度小還好,一旦很長,這個(gè)開銷挺大,這是個(gè)好的編程習(xí)慣。
//查閱代碼得知data函數(shù)有兩個(gè)重載
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)
{
}
//至于什么時(shí)候調(diào)用.data()會(huì)淺拷貝,酷碼大佬說是當(dāng)QByteArray被const修飾的時(shí)候
const QByteArray data;
//淺拷貝
const char *d = data.data();
//酷碼大佬補(bǔ)充:自Qt 5.7版本以來,引入了qAsConst函數(shù),專用于無腦轉(zhuǎn)換。
//這個(gè)函數(shù)實(shí)現(xiàn)了C++17標(biāo)準(zhǔn)中的std::as_const()函數(shù)的功能,將一個(gè)非常量的左值轉(zhuǎn)為常量的左值。
//增加qAsConst函數(shù)是為了Qt自己的非const 的容器能實(shí)現(xiàn)C++11標(biāo)準(zhǔn)的基于范圍的循環(huán)。
//該函數(shù)主要用于qt容器在隱式共享中不被detach。
QString s = "abc";
//下面會(huì)深拷貝引起性能損失
for (QChar ch : s)
//不會(huì)深拷貝
for (QChar ch : qAsConst(s))
//下面也是淺拷貝,但是在編程時(shí)、在現(xiàn)實(shí)中,聲明為const往往不容易做到。
const QString s;
for (QChar ch : s)
//總結(jié):對(duì)Qt自己實(shí)現(xiàn)的容器如:QVector、QMap、 QHash、QLinkedList、QList等,如果一定要用基于for(var : container)范圍的循環(huán),則請(qǐng)用如下形式:
for (var : qAsConst(container))
- 新版的Qt6.5在ubuntu上編譯運(yùn)行程序后會(huì)提示 qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found. ,無法正常彈出窗體程序,你需要主動(dòng)安裝xcb的相關(guān)庫。sudo apt install libxcb*
- 有些場(chǎng)景下我們需要在 QApplication a(argc, argv); 前面執(zhí)行一些處理,比如 QApplication::setAttribute 就必須在最前面執(zhí)行,而很多時(shí)候這個(gè)設(shè)置的參數(shù)不能改寫死,畢竟現(xiàn)場(chǎng)的環(huán)境千差萬別,希望通過配置文件來配置,那么問題來了,讀取配置文件一般需要指定路徑才能正常讀取到,如果是 ./ 這種,很可能未必是應(yīng)用程序的當(dāng)前路徑,如果你是雙擊運(yùn)行的程序,那肯定是應(yīng)用程序的當(dāng)前路徑,不是雙擊運(yùn)行那就是系統(tǒng)環(huán)境中的當(dāng)前路徑,意味著你開機(jī)啟動(dòng)或者用system、QProcess等方式在開機(jī)后調(diào)用啟動(dòng)的話,就未必正確了。為了保證這個(gè)路徑的正確,必須從main函數(shù)的 argv 第一個(gè)值獲取,通過查閱Qt自身代碼中獲取路徑,也是從這個(gè)參數(shù)獲取。
//程序最前面獲取應(yīng)用程序路徑和名稱
static void getCurrentInfo(char *argv[], QString &path, QString &name);
//程序最前面讀取配置文件節(jié)點(diǎn)的值
static QString getIniValue(const QString &fileName, const QString &key);
static QString getIniValue(char *argv[], const QString &key, const QString &dir = QString());
void QtHelper::getCurrentInfo(char *argv[], QString &path, QString &name)
{
//必須用fromLocal8Bit保證中文路徑正常
QString argv0 = QString::fromLocal8Bit(argv[0]);
QFileInfo file(argv0);
path = file.path();
name = file.baseName();
}
QString QtHelper::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 QtHelper::getIniValue(char *argv[], const QString &key, const QString &dir)
{
QString path, name;
QtHelper::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 = QtHelper::getIniValue(argv, "OpenGLType").toInt();
QtHelper::initOpenGL(openGLType);
QApplication a(argc, argv);
...
}
- 當(dāng)我們對(duì)QTableView/QTreeView/QTableWidget/QTreeWidget某行選中后,會(huì)發(fā)現(xiàn)某些單元格設(shè)置的前景色被覆蓋了,比如設(shè)置的紅色,一旦選中就變成了白色,這肯定不是我們想要的,需要用自定義委托將其去掉。
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);
}
//對(duì)所有單元格設(shè)置該委托
ui- >tableWidget- >setItemDelegate(new ItemDelegate);
- 有些時(shí)候我們需要在項(xiàng)目文件比如pro/pri中識(shí)別當(dāng)前Qt套件是否存在某個(gè)模塊以及是否引入過某個(gè)模塊,存在則引入,同時(shí)也希望代碼中也能識(shí)別是否引入過某個(gè)模塊比如sql模塊,判斷后再進(jìn)行對(duì)應(yīng)的處理。
//項(xiàng)目文件中判斷
//如果當(dāng)前套件中有multimedia模塊則引入multimedia模塊
qtHaveModule(multimedia) {QT += multimedia}
//在項(xiàng)目文件中已經(jīng)通過 QT += multimedia 引入過模塊
contains(QT, multimedia) {}
//代碼文件判斷
#ifdef QT_MULTIMEDIA_LIB
qDebug() < < "multimedia module is enabled";
#else
qDebug() < < "multimedia module is not enabled";
#endif
- 對(duì)MDI窗體區(qū)域設(shè)置背景顏色透明,會(huì)發(fā)現(xiàn) QMdiArea{background:transparent;} 無效,哪怕是指定顏色 QMdiArea{background:#ff0000;} 或者 QMdiArea{background-color:#ff0000;} 都不行,這就很無語了,原來要用弱屬性機(jī)制才行。QMdiArea{qproperty-background:transparent;}
- 當(dāng)樣式中啟用了禁用樣式 *:disabled{xxx} 的時(shí)候,會(huì)發(fā)現(xiàn)MDI子窗體無法拉伸了,這應(yīng)該是Qt內(nèi)部的BUG,怎么解決呢,只需要重新設(shè)置MDI這個(gè)類別的禁用樣式的邊框樣式即可。QMdiSubWindow:disabled{border:8px solid rgba(0,0,0,0);}
- 用QProcess執(zhí)行命令或者啟動(dòng)可執(zhí)行文件,默認(rèn)寫法不支持帶空格的路徑,比如 Program Files ,需要在這個(gè)路徑前后加上雙引號(hào)才行,估計(jì)可能內(nèi)部會(huì)用空格分割字符串導(dǎo)致解析失敗。普通路徑加上引號(hào)也能正常執(zhí)行,所以為了確保以防萬一,統(tǒng)一加上引號(hào)即可。
QString cmd = "c:/Program Files/a.exe";
//下面這個(gè)會(huì)執(zhí)行失敗
QProcess::startDetached(cmd);
//前后加上引號(hào)就可以正常執(zhí)行
cmd = """ + cmd + """;
QProcess::startDetached(cmd);
- 在循環(huán)中取值,臨時(shí)變量的定義盡量在循環(huán)外層定義,每次在循環(huán)里層定義會(huì)增加開銷,特別是復(fù)雜類型比如QString(基礎(chǔ)類型比如int/bool差別不大),循環(huán)次數(shù)越多,性能差別越大。
void MainWindow::on_pushButton_clicked()
{
QElapsedTimer timer;
timer.start();
QString s;
QString text = "abc";
for (int i = 0; i < 10000; ++i) {
s = text.at(0);
}
qDebug() < < "方式1" < < timer.nsecsElapsed();
}
void MainWindow::on_pushButton_2_clicked()
{
QElapsedTimer timer;
timer.start();
QString text = "abc";
for (int i = 0; i < 10000; ++i) {
QString s = text.at(0);
}
qDebug() < < "方式2" < < timer.nsecsElapsed();
}
//debug模式下方式1比方式2快6倍+
//release模式下方式1比方式2快30倍+
- Qt的屬性機(jī)制非常強(qiáng)大,除了可以用來控制樣式表,也可以很方便的用來傳值,比如qml中的值傳遞,有時(shí)候我們寫了一個(gè)通用類,希望這個(gè)類可以做很多事情,但是又希望其中有一些特殊變量存取值,一種辦法是直接定義私有變量,提供get/set接口函數(shù),還有一種偷懶的辦法就是用屬性setProperty/property,然Qt內(nèi)部從元對(duì)象數(shù)據(jù)層面自己管理,這樣不用在類中寫對(duì)應(yīng)的變量和get/set函數(shù)。但是肯定有性能損耗,性能上肯定比變量低,所以要看具體的實(shí)際需求,如果不是非常頻繁的調(diào)用setProperty/property,通用性優(yōu)先的話,那用屬性機(jī)制會(huì)更方便。個(gè)人推薦方式三,繼承通用類,在子類中增加set/get。
void MainWindow::on_pushButton_clicked()
{
QElapsedTimer timer;
timer.start();
for (int i = 0; i < 10000; ++i) {
Test *t = new Test;
//t- >setId(i);
//t- >setName("test");
t- >getName();
}
qDebug() < < "方式1" < < timer.nsecsElapsed();
}
void MainWindow::on_pushButton_2_clicked()
{
QElapsedTimer timer;
timer.start();
for (int i = 0; i < 10000; ++i) {
Test *t = new Test;
//t- >setProperty("id", i);
//t- >setProperty("name", "test");
t- >property("name").toString();
}
qDebug() < < "方式2" < < timer.nsecsElapsed();
}
//對(duì)比測(cè)試和具體的變量類型無關(guān)/int和QString類型產(chǎn)生的性能差別一樣
//setProperty比setxxx方式性能差3倍+
//property比getxxx方式性能差1.3倍
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。
舉報(bào)投訴
-
內(nèi)存
+關(guān)注
關(guān)注
8文章
3002瀏覽量
73884 -
編程
+關(guān)注
關(guān)注
88文章
3592瀏覽量
93596 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4306瀏覽量
62431 -
char
+關(guān)注
關(guān)注
0文章
11瀏覽量
3705
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
如何將orcad轉(zhuǎn)成mentor_expedition
使用Orcad畫電路圖后,將每一個(gè)零件的PCB Footprint填入,格式如下圖所示
發(fā)表于 06-24 17:22
?2891次閱讀
windows下QT編程中_TCHAR與QString之間的轉(zhuǎn)換
;utf16()#define TCHARToQString(x)QString::fromUtf16((x))#define TCHARToQStringN(x,y)QString::fromUtf16
發(fā)表于 03-21 11:22
如何將PowerPCB轉(zhuǎn)成Protel的詳細(xì)過程和軟件
如何將PowerPCB轉(zhuǎn)成Protel的詳細(xì)過程第一步:用PowerPCB打開文件,選擇“File”---“Export”導(dǎo)出,如圖:導(dǎo)出格式Format選擇PowerPCBV3.5的,然后
發(fā)表于 11-24 16:25
如何將char型指針強(qiáng)制轉(zhuǎn)換成UCHAR型指針
如何將char型指針強(qiáng)制轉(zhuǎn)換成UCHAR型指針??????、、
發(fā)表于 12-21 15:51
如何將ASCII碼轉(zhuǎn)成16進(jìn)制數(shù)?
如ASCII碼“”3133”,轉(zhuǎn)成16進(jìn)制數(shù)應(yīng)該是0x13,請(qǐng)問VHDL語言怎么寫呢?
發(fā)表于 05-16 18:51
如何將PDF轉(zhuǎn)成CAD
`現(xiàn)在很多設(shè)計(jì)圖紙等操作者都需要對(duì)PDF格式得圖紙進(jìn)行二次編輯,但是PDF文件又不能直接進(jìn)行編輯修改,那我們?cè)撊绾尾僮髂兀覀兛梢?b class='flag-5'>將PDF轉(zhuǎn)成CAD文件然后再進(jìn)行轉(zhuǎn)換得操作,接下來就讓小編來具體介紹
發(fā)表于 07-03 18:17
如何將orcad轉(zhuǎn)成mentor_expedition?
請(qǐng)教大神如何將orcad轉(zhuǎn)成mentor_expedition?
發(fā)表于 04-23 07:22
請(qǐng)教一下RK3568是如何將EDP轉(zhuǎn)成VGA-out的
請(qǐng)教一下RK3568是如何將EDP轉(zhuǎn)成VGA-out的?
發(fā)表于 03-02 06:29
如何將一個(gè)INT型數(shù)據(jù)轉(zhuǎn)換成2個(gè)CHAR型數(shù)據(jù)?
如何將一個(gè)INT型數(shù)據(jù)轉(zhuǎn)換成2個(gè)CHAR型數(shù)據(jù)?
發(fā)表于 11-03 06:20
如何將Cadence的原理圖和PCB轉(zhuǎn)成PADS資料下載
電子發(fā)燒友網(wǎng)為你提供如何將Cadence的原理圖和PCB轉(zhuǎn)成PADS資料下載的電子資料下載,更有其他相關(guān)的電路圖、源代碼、課件教程、中文資料、英文資料、參考設(shè)計(jì)、用戶指南、解決方案等資料,希望可以幫助到廣大的電子工程師們。
發(fā)表于 04-19 08:54
?46次下載
數(shù)控直流穩(wěn)壓電源如何將交流電壓轉(zhuǎn)成直流電壓?
數(shù)控直流穩(wěn)壓電源如何將交流電壓轉(zhuǎn)成直流電壓? 數(shù)控直流穩(wěn)壓電源是一種將交流電壓轉(zhuǎn)換為直流電壓的裝置。在現(xiàn)代電子設(shè)備中,直流電壓廣泛應(yīng)用,因?yàn)樗诜€(wěn)定性、可調(diào)性和可靠性方面具有優(yōu)勢(shì)。為了滿足設(shè)備的要求
評(píng)論