- Qt天生就是linux的,從linux開始發展起來的,所以不少Qt程式員經常的開發環境是linux,比如常用的ubuntu等系統,整理了一點常用的linux命令,
| 命令 | 功能 |
|---|---|
| sudo -s | 切換到管理員,如果是 sudo -i 切換后會改變當前目錄, |
| apt install g++ | 安裝軟體包(要管理員權限),另一個派系的是 yum install |
| cd /home | 進入home目錄 |
| ls | 羅列當前所在目錄所有目錄和檔案 |
| ifconfig | 查看網卡資訊包括IP地址,windows上是 ipconfig, |
| tar -zxvf bin.tar.gz | 解壓檔案到當前目錄 |
| tar -jxvf bin.tar.xz | 解壓檔案到當前目錄 |
| tar -zxvf bin.tar.gz -C /home | 解壓檔案到/home目錄,記住是大寫的C, |
| tar -zcvf bin.tar.gz bin | 將bin目錄壓縮成tar.gz格式檔案(壓縮比一般) |
| tar -jcvf bin.tar.xz bin | 將bin目錄壓縮成tar.xz格式檔案(壓縮比高,推薦) |
| tar -… | j z 表示不同的壓縮方法,x表示解壓,c表示壓縮, |
| gedit 1.txt | 用記事本打開文本檔案 |
| vim 1.txt | 用vim打開檔案,很多時候可以縮寫用vi, |
| ./configure make -j4 make install | 通用編譯原始碼命令, 第一步./configure執行配置腳本,第二步make -j4啟用多執行緒編譯,第三步make install安裝編譯好的檔案, |
| ./configure -prefix /home/liu/Qt-5.9.3-static -static -sql-sqlite -qt-zlib -qt-xcb -qt-libpng -qt-libjpeg -fontconfig -system-freetype -iconv -nomake tests -nomake examples -skip qt3d -skip qtdoc | Qt通用編譯命令 |
| ./configure -prefix /home/liu/Qt-5.9.3-static -static -release -nomake examples -nomake tests -skip qt3d | 精簡編譯命令 |
| ./configure --prefix=host --enable-static --disable-shared --disable-doc | ffmpeg編譯命令 |
- Qt自帶的日志重定向機制非常簡單好用,自從用了以后再也不用什么斷點除錯啥的了,在需要的地方支持qdebug輸出對應的資訊,而且發布程式以后也可以開啟除錯日志將其輸出查看等,
//Qt5開始提供了日志背景關系資訊輸出,比如輸出當前列印訊息所在的代碼檔案、行號、函式名等,
//如果是release還需要在pro中加上 DEFINES += QT_MESSAGELOGCONTEXT 才能輸出背景關系,默認release關閉的,
//切記不要在日志鉤子函式中再寫qdebug之類的,那樣就死回圈了,
//日志重定向一般就三種處理
//1: 輸出到日志檔案比如txt文本檔案,
//2: 存盤到資料庫,可以分類存盤,以便相關人員查詢分析,
//3: 重定向到網路,對方用小工具連接程式后,所有列印資訊通過tcp發過去,
//日志重定向
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
void Log(QtMsgType type, const QMessageLogContext &context, const QString &msg)
#else
void Log(QtMsgType type, const char *msg)
#endif
{
//加鎖,防止多執行緒中qdebug太頻繁導致崩潰
static QMutex mutex;
QMutexLocker locker(&mutex);
QString content;
//這里可以根據不同的型別加上不同的頭部用于區分
switch (type) {
case QtDebugMsg:
content = QString("%1").arg(msg);
break;
case QtWarningMsg:
content = QString("%1").arg(msg);
break;
case QtCriticalMsg:
content = QString("%1").arg(msg);
break;
case QtFatalMsg:
content = QString("%1").arg(msg);
break;
}
//加上列印代碼所在代碼檔案、行號、函式名
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
if (SaveLog::Instance()->getUseContext()) {
int line = context.line;
QString file = context.file;
QString function = context.function;
if (line > 0) {
content = QString("行號: %1 檔案: %2 函式: %3\n%4").arg(line).arg(file).arg(function).arg(content);
}
}
#endif
//將內容傳給函式進行處理
SaveLog::Instance()->save(content);
}
//安裝日志鉤子,輸出除錯資訊到檔案,便于除錯
void SaveLog::start()
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
qInstallMessageHandler(Log);
#else
qInstallMsgHandler(Log);
#endif
}
//卸載日志鉤子
void SaveLog::stop()
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
qInstallMessageHandler(0);
#else
qInstallMsgHandler(0);
#endif
}
- 自從c++11標準以后,各種語法糖層出不窮,其中lambda運算式用的最廣,基本上從Qt5以后就支持lambda運算式,對于習慣了c99的老一輩的程式員來說,這玩意是個新鮮事物,這里特意做個小理解筆記,
- 代碼格式:capture mutable ->return-type {statement}
- [capture]:捕捉串列,捕捉串列總是出現在Lambda函式的開始處,實際上,[]是Lambda引出符,編譯器根據該引出符判斷接下來的代碼是否是Lambda函式,捕捉串列能夠捕捉背景關系中的變數以供Lambda函式使用,
- (parameters):引數串列,與普通函式的引數串列一致,如果不需要引數傳遞,則可以連同括號 () 一起省略,
- mutable:mutable修飾符,默認情況下,Lambda函式總是一個const函式,mutable可以取消其常量性,在使用該修飾符時,引數串列不可省略(即使引數為空),
- ->return-type:回傳型別,用追蹤回傳型別形式宣告函式的回傳型別,我們可以在不需要回傳值的時候也可以連同符號 -> 一起省略,此外,在回傳型別明確的情況下,也可以省略該部分,讓編譯器對回傳型別進行推導,
- {statement}:函式體,內容與普通函式一樣,不過除了可以使用引數之外,還可以使用所有捕獲的變數,
捕捉串列有以下幾種形式:
- [var]表示值傳遞方式捕捉變數var,
- [=]表示值傳遞方式捕捉所有父作用域的變數(包括this),
- [&var]表示參考傳遞捕捉變數var,
- [&]表示參考傳遞方式捕捉所有父作用域的變數(包括this),
- [this]表示值傳遞方式捕捉當前的this指標,
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//按鈕單擊不帶引數
connect(ui->pushButton, &QPushButton::clicked, [] {
qDebug() << "hello lambda";
});
//按鈕單擊帶引數
connect(ui->pushButton, &QPushButton::clicked, [] (bool isCheck) {
qDebug() << "hello lambda" << isCheck;
});
//自定義信號帶引數
connect(this, &MainWindow::sig_test, [] (int i, int j) {
qDebug() << "hello lambda" << i << j;
});
emit sig_test(5, 8);
}
- 由于Qt版本眾多,有時候為了兼容多個版本甚至跨度Qt4/Qt5/Qt6的兼容,有些頭檔案或者類名等變了或者新增了,需要用到Qt版本的判斷,需要注意的是如果在頭檔案中使用 QT_VERSION_CHECK 需要先引入#include "qglobal.h"不然編譯失敗,因為 QT_VERSION_CHECK 這個函式在 qglobal.h 頭檔案中,
//至少要包含 qglobal.h,理論上Qt所有的類都包含了這個頭檔案,所以你引入Qt的其他頭檔案也行比如 qobject.h
#include "qglobal.h"
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
#include "qscreen.h"
#else
#include "qdesktopwidget.h"
#endif
- 在使用QString轉換到char *或者const char *的時候,務必記得分兩步來完成,血的教訓,在一個場景中,就因為沒有分兩步走,現象是msvc的debug例外release正常,mingw和gcc的debug和release都正常,這就很無語了,找問題找半天,對比法排除法按道理要么都有問題才對,
- 轉換前QString的內容無關中文還是英文,要出問題都一樣,
- 轉換中QByteArray無關具體型別,toUtf8、toLatin1、toLocal8Bit等方法,要出問題都一樣,
- 轉換后無關char *還是const char *,要出問題都一樣,
- 出問題的隨機性的,概率出現,理論上debug的概率更大,
- 根據酷碼大佬分析msvc為了方便除錯,debug會在記憶體釋放后做填充,release則不會,
QString text = "xxxxx";
//下面這樣轉換很可能會有問題
char *data = text.toUtf8().data();
//分兩步轉換肯定不會有問題
QByteArray buffer = text.toUtf8();
char *data = buffer.data();
const char *data = buffer.constData();
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/342205.html
標籤:其他
下一篇:引發C++軟體例外的常見原因分析
