從C++到Qt開發過程
本文介紹的是從C++到Qt開發過程,而對于Qt,想必大家都很熟悉了,Qt 是一個跨平臺的 C++ 圖形用戶界面庫,Qt是完全面向對象的,很容易擴展,并且允許真正地組件編程。那么先看本文的介紹吧。
在Qt論壇經常看到網友抱怨:
QPixmap("dbzhang800.png") 加載圖片不成功
QFile("dbzhang800.txt") 打開文件失敗
...
遇到這種問題,我一般回答:請注意區分進程的"工作目錄 "與程序所在的目錄 。但這種回答似乎還是顯得太蒼白了,既然如此,整理一下吧。
用到了相對路徑,你清楚"相對"是相對那個目錄的么?
當你抱怨Qt時,你知道它與Qt無關么?
Qt 是 C++ 的庫,我們還是從C++開始看吧(注:你可能會對 用ISO C++實現自己的信號槽(另類的Qt學習) 以及 從 C++ 到 Qt 感興趣) 。
相對路徑
剛接觸文件操作時,我們應該都寫過這種簡單的小程序吧:
- #include <stdio.h>
- int main()
- {
- FILE * pFile = fopen ("dbzhang800.txt" , "r");
- if (pFile == NULL) {
- perror ("Error opening file");
- } else {
- //do something
- fclose (pFile);
- }
- return 0;
- }
我們在可執行文件的同級目錄下放置dbzhang800.txt文件,然后調用編譯器編譯程序
- cl abc.cpp
或
- g++ abc.cpp -o abc
然后運行程序 abc,一切都很正常,是不?
可能是這個原因吧,導致很多人誤認為 :相對目錄相對的就是應用程序所在的目錄!
你有沒有沒試過:
- |-- dir1\
- | |-- abc(.exe)
- | `-- dbzhang800.txt
- |
- `-- dir2\
如果你在終端(或cmd窗口)中切換目錄到 dir2,然后通過 ../dir1/abc 運行程序,你的程序還能找到文本文件么?
如果你想讓它找到,此時文件應該放置到哪個目錄?
#p#
工作目錄
遇到相對路徑,我們肯定繞不過工作目錄(working directory)。它有時也被稱為當前工作目錄(c urrent w orking d irectory),所有的相對路徑都是從工作目錄開始解釋的。 我們可以通過_chdir 等函數來更改進程的工作目錄。
接前面的例子,如果你真的對工作目錄沒有感覺,不妨直接輸出來自己看看(網絡上你可能會看到其他posix等提供的函數,我們只使用ISO C++標準中的函數):
- #include <direct.h>
- #include <stdlib.h>
- #include <stdio.h>
- int main( void )
- {
- char* buffer;
- if( (buffer = _getcwd( NULL, 0 )) == NULL ) {
- perror( "_getcwd error" );
- } else {
- printf( "Current Dir: %s \n", buffer);
- free(buffer);
- }
- }
(1)我們調用 _getcwd 來獲得當前的工作目錄
(2)你可以在終端或cmd中切換到其他目錄,通過絕對路徑來調用你的這個程序,來觀察輸出
(3)如果你在linux下,你可以創建啟動器,然后啟動器中可以設置工作目錄
(4)如果你在windows下,你可以為其創建快捷方式,快捷方式屬性中可以設置/修改工作目錄。
進程內修改工作目錄
看個無聊的例子:
- #include <stdio.h>
- #include <direct.h>
- int main()
- {
- _chdir("c:\\temp");
- FILE * pFile = fopen ("dbzhang800.txt" , "r");
- if (pFile == NULL) {
- perror ("Error opening file");
- } else {
- //do something
- fclose (pFile);
- }
- return 0;
- }
使用 _chdir 修改工作目錄
現在,程序將去打開C盤temp目錄下的文本文件
注:_chdir 和 _getcwd 都有對應的寬字符(wchar_t)版本,此處不涉及(如果你要使用寬字符,不妨先考慮看看此文C 源文件內的中文(2) )。
回到Qt
Qt 是C++的庫,所以上面的東西你完全可以直接用。不過由于Qt提供更好用的東西QDir,我想你應該不會想著在Qt中使用前面提到的C、C++的中函數。
注意:如果你要操作的文件是只讀的,而且程序編譯完成后這些文件不需要變化,那么請首先考慮采用Qt的資源文件.qrc(本文不涉及這部分)。
下面:我們不妨看看前兩個函數在Qt中的等價物。
獲得工作目錄
如果你對工作目錄依然不熟悉,使用相對路徑出現問題時,請首先考慮使用下列語句:
- qDebug()<<QDir::currentPath();
看看和你預想的是否相符。
修改工作目錄
你很少需要這個操作
如果你用到了,請注意
- bool QDir::setCurrent ( const QString & path ) [static]
而不是
- bool QDir::cd ( const QString & dirName )
- bool QDir::cdUp ()
- void QDir::setPath ( const QString & path )
程序所在目錄 如何知道你程序自己在那個目錄下,這是一個和平臺相關的問題(ISO C、C++ 目前似乎還不能告訴我們答案)。幸好Qt提供了很好的封裝了:
- QString QCoreApplication::applicationDirPath () [static]
如果你想使用相對路徑訪問和可執行程序的同目錄下的文件,你可以將工作目錄設置成該目錄!
或者(這應該是更好點的方法),用該目錄和你的相對路徑先直接組合成絕對路徑再使用。
可是 ,你有沒有這個問題:當我們在windows下使用Qt的時候,生成的可執行程序會在debug或release目錄下,我們要訪問的文件在 project.pro 文件所在目錄(或其子目錄)下。這可怎么辦是好?
一個有用的函數
如果你想訪問工程目錄下的doc/dbzhang800.txt文件:
- |-- project.pro
- |-- doc\
- | `-- dbzhang800.txt
- |
- |-- release\
- | `-- abc.exe
- |
- `-- debug\
- `-- abc.exe直接
QFile(doc/dbzhang800.txt);好用么?如果在QtCreator 等環境下運行,一般可以工作,可是,進到debug下雙擊,卻不工作了(不要告訴我你看了上面內容還不知道原因哈)。
問題的解決方案來自C++ GUI Qt4 編程一書,我相信你肯定見過這個函數:
- QDir directoryOf(const QString &subdir)
- {
- QDir dir(QApplication::applicationDirPath());
- #if defined(Q_OS_WIN)
- if (dir.dirName().toLower() == "debug"
- || dir.dirName().toLower() == "release"
- || dir.dirName().toLower() == "bin")
- dir.cdUp();
- #elif defined(Q_OS_MAC)
- if (dir.dirName() == "MacOS") {
- dir.cdUp();
- dir.cdUp();
- dir.cdUp();
- }
- #endif
- dir.cd(subdir);
- return dir;
- }
這個函數怎么用? 我們只需要:
- QFile(directoryOf("doc").absoluteFilePath(dbzhang800.txt));
shadow build
qmake 很早就提供shadow build功能,但也就QtCreator默認使用了該功能以后,大部分人才開始注意到它。
- |-- project-sources/
- | |-- project.pro
- | `-- main.cpp
- |
- |-- build-vs2008/
- | |-- Debug/
- | | `-- main.exe
- | `-- Release/
- | `-- main.exe
- |-- build-vs2005/
- |-- build-mingw/
- |-- build-symbian/
- |-- build-dbzhang800/
- |-- ..
.這兒沒有神奇之處,只不過一般資料上介紹qmake都是這樣說的:
- qmake project.pro
make而 qtcreator 是這么做的
- cd ../build-vs2008
- qmake ../project-sources/project.pro
- make
這種情況下,我們一般需要將一些文件拷貝到構建目錄下,具體可參考 http://blog.csdn.net/dbzhang800/archive/2011/04/23/6343838.aspx ***給的一段代碼。
小結:本章主要講述了從相對路徑說開來,C++到Qt的過程,相信你也學到了不少。希望本篇文章對你有幫助!!!