第一章第一節:創建和調試Qt項目

您好!歡迎加入Qt MOOC!

本主題涵蓋了您在學習本課程時所需的大部分基本知識。我們將從課程的角度,以練習的形式來討論Qt項目。還會介紹一些重要概念,這些概念將幫助您了解Qt的基礎知識。我們使用Qt的官方文檔作為輔助材料,這會讓您熟悉Qt的官方文檔。另外,我們還將討論構建,qmake和調試信息等。

如果所有這些對您來說都已經很熟悉了,你可以直接去完成練習,然后進入更具體的主題。如果您在完成Hello World練習時不知道發生了什么情況,請回來閱讀基礎知識,我們不會對您有任何偏見!

在開始繁重的工作之前,我們將介紹一些基本概念來幫助您開始。它們是Qt中的全局聲明、模塊和命名空間。

1. 全局聲明和宏

讓我們來討論一下Qt中的全局聲明,您可以在Qt文檔中找到一個完整的全局聲明列表。

全局聲明包括類型、函數和宏。在進入下一章之前,您絕對不需要記住這個列表,但重要的是,您要知道它是什么,可以用它來做什么,因為您可能會發現它在各種場合下都非常有用。在本主題的最后,我們將討論在全局聲明中找到的一些有用的調試函數。

類型定義部分是用于方便基本類型的定義(其中一些類型保證了Qt在所有支持的平臺上的特定位大小),部分是與Qt消息處理相關的類型。這些函數與生成消息、Qt版本處理以及比較和調整對象值有關。最后,一些聲明的宏允許程序員將編譯器或平臺特定的代碼添加到他們的應用程序中,而另一些宏則是用于更大操作的方便宏。

如果有必要,我們會在作業或學習主題中明確地向您介紹全局聲明列表。

2. Qt模塊和命名空間

接下來,讓我們來討論一下Qt中的模塊。這是Qt中的模塊列表。

要將模塊包含到項目中,您需要將它們包含在項目的.pro文件中。如果使用qmake,則默認情況下將包括Core和GUI模塊。如果您沒有在項目中使用GUI模塊(無論如何,在開始時大部分時間我們都不會使用GUI模塊),只需在您的項目.pro文件中寫入QT -= GUI即可將其禁用。所有其他Qt模塊都依賴于Qt Core模塊。

接下來,我們看一下有關命名空間及其在Qt中的用法的一些基本知識。這是Qt中主要命名空間的列表。當然,該課程我們不會使用所有的命名空間,但是在開始之前,我們相信事先了解這個列表會對您有所幫助。

讓我們舉一個包含命名空間的示例!假設您想在代碼中包含QtConcurrent命名空間。讓我們仔細看看QtConcurrent的文檔頁面:

image

要包含QtConcurrent命名空間,您需要在兩個地方進行具體說明:相關文件的頭文件(#include <QtConcurrent>),

image

和項目.pro文件(QT += concurrent)。

image

3. Qt命名空間

Qt命名空間中,您會發現Qt庫中使用了各種各樣的標識符。在進入本主題的下一章之前,我們希望您能記住這些列表。

只是開個玩笑!我們只是想讓您知道,如果您碰巧需要使用命名空間,可以把它作為參考材料。

4. TMC練習的結構

講完基礎知識之后,該看一下TMC練習的結構組成了。

每個練習都位于每周主練習目錄中自己的子目錄中。該練習由根級別的.pro文件以及幾個目錄組成。

根級別的.pro文件是練習項目的項目文件。我們將在本章后面進一步討論項目文件。但是現在,我們將重點放在項目結構上。

用于測試您的練習的本地測試位于test_runner目錄中。

如果您在弄清楚為什么您的練習不能通過測試時遇到了問題,并且您已經用盡了所有其他方法,那么可能值得查看測試運行程序文件。弄清楚測試的內容可能會給您一些線索,讓您知道代碼中可能存在的問題。如果有助于您更好的理解問題的話,您甚至可以修改本地測試。在極少的情況下,問題可能是由于測試本身是錯誤的。在這種情況下,我們建議加入課程頻道,看看其他人是否有同樣的問題。我們已經做了我們所能做的一切來確保這種情況不會發生,但總有特殊情況。

請注意,本地測試只是為了告訴您,您的練習是否完成并準備好提交。您無法根據自己的偏好修改測試,并期望通過提交一份未完成的作業來通過練習!我們將在您獲得分數之前在服務器上測試您的練習!有時候,服務器端可能會有隱藏的測試,以確保您不會根據測試的目的來嘗試完成練習,而是完成實際的練習來支持您的學習。

src目錄是神奇個地方,它是我們編程的位置。

它包括每個練習項目的相關源文件和頭文件。在某些情況下,庫可能包含額外的目錄,在某些情況下,我們可能會要求您創建新的目錄。沒人知道!沒有人知道什么時候!沒有人知道!但我們稍后會算出來。

您是否已經注意到每個目錄都有自己的.pro文件?這樣做的原因是,我們包含在練習目錄中的每一個子目錄實際上都是實際練習項目中的子項目。讓我們詳細介紹一下根目錄.pro文件:

TEMPLATE = subdirs
SUBDIRS += \
      src \
      test_runner

      test_runner.depends = src

它會告訴qmake(我們將在本章的下一步討論它)該練習項目遵循一個名為subdirs的構建模板,并定義了包含在該項目中的子目錄。使用子目錄模板要求每個聲明的子目錄都是其自己的項目,并且在子目錄中包含它自己的項目文件。最后,我們聲明test runner子目錄依賴于src目錄。這是因為我們想在構建test runner之前構建您的練習,這樣test runner就有東西要測試了。

5. qmake

qmake工具可以幫助您在各種平臺開發項目時簡化構建過程。它會自動生成Makefile,因此只需幾行信息即可創建Makefile。您還可以將qmake用于其他軟件項目,無論它是不是使用Qt編寫的。

qmake根據項目文件中的信息生成一個Makefile。項目文件使用擴展名.pro,通常由Qt Creator中的項目模板創建。項目文件由開發人員處理,以指定他們qmake要用于其項目的指令集,并且通常很簡單。不過您也可以為復雜的項目創建更復雜的項目文件。我們將在本章后面進一步討論項目文件,但由于qmake使用的是存儲在項目文件中的信息,所以在談到qmake時,我們無法避免地會談到它們的內容。

qmake的行為受項目構建過程中的變量聲明的影響。其中一些聲明資源對每個平臺都是通用的,例如頭文件和源文件。其他的用于定制特定平臺上編譯器和鏈接器的行為。

讓我們再一次參考我們的練習結構來詳細說明,源目錄中的.pro文件如下:

QT -= gui

TARGET = main

CONFIG += c++11 console
CONFIG -= app_bundle

win32 {
     CONFIG -= debug_and_release debug_and_release_target
}

DEFINES += QT_DEPRECATED_WARNINGS

SOURCES += \
     main.cpp \
     hello.cpp

 HEADERS += \
      hello.h

您可以參考01_HelloWorld的目錄結構和文件組成。也可以參照qmake變量引用,并思考前面提到的.pro文件代碼中的聲明。您要知道我們要告訴qmake什么以及為什么。win32位可能不是完全不言自明的。

特定于平臺的變量遵循它們的擴展或修改的變量的命名模式,但在其名稱中包括相關平臺的名稱。例如,LIBS可用于指定項目需要鏈接的庫列表。如下:

unix:LIBS += -L/usr/local/lib -lmath
win32:LIBS += c:/mylibs/math.lib

如果您想自己做一些探索,我們建議您查看qmake變量的完整列表,以便自行瀏覽。

6. .pro文件

在項目文件中,變量用于保存字符串列表。在最簡單的項目中,這些變量會告知qmake要使用的配置選項,或者提供要在構建過程中使用的文件名和路徑。

qmake會在每個項目文件中查找某些變量,并使用這些變量的內容來確定應該向Makefile寫入什么。例如,HEADERSSOURCES變量中的值列表用于聲明qmake與項目文件位于同一目錄中的頭文件和源文件。

只要您使用qmake,默認情況下就會包括Core和GUI模塊。

變量還可以在內部用于存儲值的臨時列表,現有的值列表可以用新值覆蓋或擴展。

以下代碼段說明了如何將值列表分配給變量:

HEADERS = mainwindow.h paintwidget.h

變量中的值列表以以下方式擴展:

SOURCES = main.cpp mainwindow.cpp \
          paintwidget.cpp
CONFIG += console

注意:第一個賦值僅包含與HEADERS變量在同一行上指定的值。第二個賦值SOURCES使用反斜杠(\)將變量中的值分成幾行。

7. Qt資源系統

Qt資源系統是一種獨立于平臺的方式,用于在應用程序的可執行文件中存儲應用程序資源(圖像、圖標、翻譯文件、數據等)。
資源在資源集合文件中qrc指定:

<!DOCTYPE RCC><RCC version="1.0">
<qresource>
    <file>images/icon.png</file>
    <file>data.txt</file>
</qresource>
</RCC>

然后將該文件包含在.pro文件中,如RESOURCES = application.qrc。指定的文件將被壓縮并包裝為一個C++靜態數組。接著可以使用像QFile或圖像類型來訪問它們,就像其他任何文件一樣:

QIcon icon(":/images/icon.png")
QFile file(":/data.txt");

8. QDebug類

QDebug類提供了一個用于調試信息的輸出流。

當開發人員需要將調試或跟蹤信息寫入設備、文件、字符串或控制臺時,就會使用QDebug。

基本用途

在通常情況下,調用qDebug()函數以獲得默認的QDebug對象以用于編寫調試信息很有用。

qDebug() << "Date:" << QDate::currentDate();
qDebug() << "Types:" << QString("String") << QChar('x') << QRect(0, 10, 50, 40);
qDebug() << "Custom coordinate type:" << coordinate;

QDebug的構造函數會接受QtMsgType值來構造一個QtDebugMsg對象。類似地,qWarning(),qCritical()qFatal()也會返回相應的消息類型的QDebug對象。

這個類還為其他情況提供了一些構造函數,包括接收QFile或用于將調試信息寫入文件,套接字,其他進程等的任何其他QIODevice子類的構造函數。接收QString的構造函數用于寫入用于顯示或序列化的字符串。

格式化選項

格式化QDebug的輸出以便于閱讀。它在參數之間會自動添加空格,并為QStringQByteArrayQChar的參數增加了引號。

您可以通過space(),nospace(),quote(),noquote()方法來調整這些選項。另外,可以將QTextStream通過管道傳送到QDebug流中。

使用QDebugStateSaver會將格式更改限制為當前范圍。resetFormat()將選項重置為默認選項。

將自定義類型寫入流

可以將許多標準類型寫入QDebug對象,而Qt提供了對大多數Qt值類型的支持。要添加對自定義類型的支持,您需要實現一個流操作符,如下面的示例所示:

QDebug operator<<(QDebug debug, const Coordinate &c)
{
    QDebugStateSaver saver(debug);
    debug.nospace() << '(' << c.x() << ", " << c.y() << ')';

    return debug;
}

9. 輸出調試信息

qDebug,qWarning,qCriticalqFatal是Qt全局聲明中定義的函數。這些函數采用格式化字符串和參數列表,類似于C語言的printf()函數。格式應為Latin-1字符串。要禁止這些類型中的任何一種,您可以使用qInstallMessageHandler安裝自己的消息處理程序。函數使用定義的調試/嚴重/致命/警告消息調用消息處理程序。它們調用消息處理程序,如果沒有消息處理程序,則將消息打印到stderr。在Windows上,大多數情況下,該消息會發送到調試器。

qDebug(const char *message, ...)

在Windows下,如果消息是控制臺應用程序,則將消息發送到控制臺。否則,它將被發送到調試器。如果在編譯過程中定義了QT_NO_DEBUG_OUTPUT,則此函數不執行任何操作。

例如:

qDebug("Items in list: %d", myList.size());

如果導入QtDebug,還可以使用更方便的語法:

qDebug() << "Brush:" << myQBrush << "Other value:" << i;

使用此語法,該函數返回一個QDebug對象,該對象配置為使用QtDebugMsg消息類型。它會自動在每個項目之間放置一個空格,并在末尾輸出換行符。它支持許多C++和Qt類型。

導入QtDebug同樣允許以使用qInfoqCriticalqWarning等效語法。

qCritical(const char *message, ...)

如果環境變量QT_FATAL_CRITICALS不為空,則退出。

例如:

void load(const QString &fileName)
{
     QFile file(fileName);
     if (!file.exists())
          qCritical("File '%s' does not exist!", qUtf8Printable(fileName));
}

-

qWarning(const char *message, ...)

如果在編譯期間定義QT_NO_WARNING_OUTPUT,則此函數不執行任何操作。如果在環境變量QT_FATAL_WARNINGS中的計數器對應的第n個警告時,它就會退出。也就是說,如果環境變量包含值1,它將在第一條消息上退出;如果它定義為10,它將在第10條消息上退出。任何非數字值都等于1。

例如:

void f(int c)
{
    if (c > 200)
        qWarning("f: bad argument, c == %d", c);
}


qFatal(const char *message, ...)

如果使用默認消息處理程序,則此函數將中止以創建核心轉儲。在Windows上,對于調試版本,此功能將報告_CRT_ERROR使您能夠將調試器連接到應用程序。

例如:

int divide(int a, int b)
{
    if (b == 0)                                
         qFatal("divide: cannot divide by zero");
    return a / b;
}

10. 影子構建

成功構建第一個Qt項目后,您可能會對構建的二進制文件感興趣。默認情況下,Qt Creator將項目作為影子構建到一個單獨的目錄(`build-ProjectName- *`)中,該目錄與源目錄分開。qmake也可以生成源代碼內部版本,但是不建議這樣做。影子構建的好處是保持該目錄的清潔,這使得在Kit或構建配置之間進行更改的速度更快。


嘿! 現在是我們第一次練習的時候了。這將是一個簡單的過程,請放心。只需從TMC下載練習模板,打開項目,然后轉到hello.cpp。
world()函數中,寫上“Hello world”作為qDebug消息,并寫上“Don't panic!” 作為qWarning消息。


Source

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,321評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,559評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,442評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,835評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,581評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,922評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,931評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,096評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,639評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,374評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,591評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,104評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,789評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,196評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,524評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,322評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,554評論 2 379

推薦閱讀更多精彩內容