搜尋此網誌

工商服務

2009年4月22日 星期三

[Qt密技]如何撰寫主控台Qt應用程式並且在命令列輸出文字?

要在主控台螢幕(Windows平台上面叫做「命令提示字元」視窗)上面輸出文字,有三種呼叫方式:其一,加入#include <QtDebug>(包含於QtGui表頭檔內,若已加入#include <QtGui>則可以省略這行)以便使用qDebug() << arg語法,至於qDebug("...", arg)語法則只需加入任何Qt表頭檔即可使用;其二,若想要透過C++的std::cout來輸出,則需要加入#include <iostream>;其三,使用C的printf()函式也無妨,並視需要加入#include <cstdlib>(所謂的視需要是指如果編譯器有發生錯誤的話才加入)。

針對C的語法,若要將QString的內容轉為printf()可以接受的字元陣列,需要多呼叫兩層,亦即先用toAscii()轉換、再用constData()取值,所以Qt裡面內建了一個方便的巨集,叫做qPrintable(),協助完成這兩個動作,以免每次都還要努力回想QString轉換成char*的步驟。

但是不管是挑選上述的何種方法來實現在命令列上面的文字輸出,都務必要在.pro專案檔內加入「CONFIG += console」這行敘述,否則無論是qDebug、cout或者printf都將不會顯示結果出來。換言之,在撰寫命令列的主控台應用程式的時候,這行敘述是絕對不可或缺的(除非「qmake -project」指令自己有偵測到該應用程式為主控台類型),否則將無法看到輸出結果,甚至可能還會誤以為是程式邏輯發生了什麼錯誤。

事實上,「CONFIG += console」是啟用主控台輸出的開關,與應用程式是否透過QCoreApplication的exec()來執行是無關的。

附帶說明,當我們將Qt應用程式執行起來的時候,基本上只有一個執行緒在跑,也就是主執行緒。像這樣:

#include <iostream>

int main(int argc, char *argv[])
{
  SomeClass w;
  w.someFunction(argv[1]);
  std::cout << "done" << endl;
  return 0;
}

並不見得每個Qt主控台應用程式都需要一個QCoreApplication物件,但是如果應用程式必須等待和處理相關事件的話(比方說接收底層物件傳遞上來的signal訊號並且做出反應),那麼就需要建立QCoreApplication物件,並呼叫其exec()來執行應用程式了。像這樣:

#include <QCoreApplication>
#include <iostream>

int main(int argc, char *argv[])
{
  QCoreApplication app(argc, argv);
  SomeClass w;
  w.someFunction(argv[1]);
  std::cout << "done" << endl;
  return app.exec();
}

我們姑且稱沒有GUI介面的為主控台應用程式,建立QCoreApplication而非QApplication物件,可以避免連結到不需要使用到的QtGui程式庫。另一方面,針對QCoreApplication,因為將會形成一直在等待事件的迴圈,所以即便邏輯運算已經完成了,程式還是不會結束,因此必須手動按下〔Ctrl+C〕組合鍵,或者是讓某個功能處理完畢的signal訊號來觸發QCoreApplication的quit(),如此程式才會順利返回,示範如下:

QCoreApplication app(argc, argv);
QObject::connect(someObject, SIGNAL(someSignal()), &app, SLOT(quit()));
return app.exec();


1 則留言:

  1. 請問如果是在Visual Studio下的QT專案,因為沒有.pro檔,要如何讓GUI和console同時並存呢?

    回覆刪除