韓元旭、餘橙、沈開洋正則表達式
Qt是一個跨平臺的C++圖形用戶界面應用程序框架。它早在1991年奇趣科技公司兩位合夥人着手開發這樣一個平臺,在2008年如日中天的諾基亞因爲看好Qt在嵌入式領域的潛力,一擲千金將它收購做爲新一代智能手機操做系統的載體,可是由於諾基亞在智能手機領域的敗北,不得已而放手Qt,終於Qt於2012被最後一位東家 Digia 公司收購。通過這幾年的發展,Qt不但擁有了完備的C++圖形庫,並且也極大的提升了Qt開發跨平臺應用程序的能力。數據庫
Qt能夠同時支持桌面應用程序開發、嵌入式開發和移動開發,甚至它能夠作移動開發,覆蓋了現有的全部主流平臺。你只須要編寫一次代碼,發佈到不一樣平臺前從新編譯便可。編程
Qt憑藉一套對原生Windows、Mac、Linux等平臺支持很好的 GUI 庫和豐富的 API 庫,使得它成爲了開發跨平臺桌面應用的一個很好的選擇。與中國一些優秀的桌面端軟件選擇本身開發多平臺的 GUI 庫不一樣,國外的不少優秀桌面應用都偏好採用跨平臺的 GUI 庫進行開發。好比在硅谷有一款很著名的文檔管理應用 DropBox,微軟自家的社交聊天工具 Skype,像極品飛車這樣大型的遊戲的GUI頁面,甚至國內的金山軟件公司推出的辦公軟件 WPS Office,固然還有咱們的AlphaBox。瀏覽器
由於Qt不只可以高效率的完成不一樣平臺GUI內容的開發,更可以高效率的完成系統級別的一些任務。這也是AlphaBox選擇使用Qt開發的緣由。安全
AlphaBox 其實包含兩個主要的進程,一塊是同步盤的引擎—C語言構建的底層同步進程,咱們稱之爲 daemon;剩下的圖形頁面以及與操做系統交互的模塊都是使用Qt進行開發的。Qt提供的豐富的跨平臺GUI組件可以保證在不一樣操做系統中 AlphaBox 都有着美觀和吻合操做系統的樣式,Qt自家生產的 IDE—Qt Creator 提供了一套很是好上手的圖形界面構建工具,即便是剛接觸Qt的小白也能夠輕鬆的繪製出想要的頁面而且可以完成核心頁面邏輯。除此以外,得益於 C++ 的加持,Qt與操做系統有着很是健壯的通訊機制,憑藉這一點,AlphaBox 可以輕鬆完成精準監控操做系統中文件的改動、創建本地數據庫進行寫入數據的等操做,不只於此,優秀的混合編程能力可以讓Qt輕鬆的與 Objective-C、C# 等語言進行混編,實現系統級別擴展的調用,這就是咱們可以在 Finder 和Windows 資源管理器中可以看到同步盤文件不一樣狀態的緣由了。bash
Qt支持 Windows、Linux/Unix、Mac OS X、Android、BlackBerry、QNX等多種平臺,併爲這些不一樣的平臺提供了統一的開發環境。多線程
C++是徹底面向對象的,這一點和Objective-c等在開發很類似。而Qt又是基於C++一種語言的擴展,你們都知道C++ 有快速、簡易、面向對象等不少優勢,因此Qt天然也繼承者C++這些的優勢。框架
Qt良好的封裝機制使得Qt的模塊化程度很是高,可重用性較好,對用戶開發來貨是很是方便的。Qt提供一種爲signals/slots(信號和槽) 的安全類型來替代callback,使得各個元件之間的協同工做變得十分簡單。模塊化
Qt包括多達 250 個以上的 C++ 類,還提供基於模板的 collections, serialization, file, I/Odevice, directory management, date/time 類。甚至還包括正則表達式的處理功能。
支持 2D/3D 圖形渲染,支持 OpenGL。
大量的開發文檔。函數
Webkit 引擎的集成,能夠實現本地界面與Web內容的無縫集成, 可是真正使得 Qt 在自由軟件界的衆多 Widgets (如 Lesstif,Gtk,EZWGL,Xforms,fltk 等等)中脫穎而出的仍是基於 Qt 的重量級軟件 KDE。
Qt提供了信號和槽機制用於完成見面操做的響應,是完成任意兩個Qt對象之通訊機制。其中,信號會在某個特定狀況或動做下被觸動,槽是等同於接受並處理信號的函數。
爲何方法不是直接調用的。中間用到 Signal 和槽機制不是畫蛇添足?
其實在咱們生活也是同樣,老闆級別的好說話,老闆給助理分派任務也好說話,可是助理給老闆分任務,可想而知會有什麼後果,在之前的統治階層確定不容許這樣的事發生。因此在分層思想中,咱們所調用的函數也是這樣的,上層能夠調用下層和同一層的函數,下層函數不能夠調用上層函數,不然程序的層次性會被打破,致使結構錯綜複雜,難以維護和管理。
那麼怎樣才能作到向上管理呢,有任務分配給老闆怎麼辦?
老闆會設立一個機構,也就是一個函數,用無限循環來查詢助理的狀態,若是助理真的有事情,這個機構就把這消息拿到老闆來處理。可是這種處理方式顯得有些複雜,咱們想要的簡單明瞭的方式是,若是助理有事件發生,能夠直接調用
老闆函數處理。
說了這麼多其實就是想說,信號和槽的最大優點在於,它完善了程序分層的思想,能夠在不改變程序的層次性的狀況下,完成由下層到上層的調用。在下層發出一個 Signal,這時上層與其想關聯的 Slot 函數就會響應。
如今,信號和槽中存在的問題是:
要想解決以上問題,就須要將相應的信號和槽鏈接起來。當指定的信號發出時,槽所在的對象就能接收到該信號,從而調用相應的槽函數執行指定的處理。
1.一個信號能夠與另外一個信號相連
connect (Object1,SIGNAL(signal1),Object2,SIGNAL(signal2));
複製代碼
表示 Object1的信號1發送能夠觸發Object2的信號1發送。
2.同一個信號能夠與多個槽相連:
connect (Object1,SIGNAL(signal2),Object2,SIGNAL(slot2));
connect (Object1,SIGNAL(signal2),Object3,SIGNAL(slot1));
複製代碼
3.同一個槽能夠響應多個信號:
connect (Object1,SIGNAL(signal2),Object2,SIGNAL(slot2));
connect (Object3,SIGNAL(signal2),Object2,SIGNAL(slot2));
複製代碼
4.鏈接能夠被移除:
這種狀況用得比較少,由於在對象被刪除時,Qt會自動移除與這個對象相關的全部鏈接。
disconnect(sender, SIGNAL(signal), receiver, SLOT(slot));
複製代碼
可是,經常使用的鏈接方式爲:
connect (Object1,SIGNAL(signal),Object2,SIGNAL(slot));
複製代碼
其中,signal 爲對象Object1的信號,slot 爲Object2的槽。
####提示: 信號與槽機制與普通函數的調用同樣,若是使用不當的話,在程序執行時也有可能產生死循環。所以,在定義槽函數時必定要注意避免間接造成無限循環,即在槽中再次發射所接收到的一樣信號。
若是一個信號與多個槽相聯繫的話,那麼,當這個信號被髮射時,與之相關的槽被激活的順序將是隨機的。
宏定義不能用在 signal 和 slot 的參數中。
信號和槽的參數個數與類型必須一致。
須要關聯的信號和槽的簽名必須是等同。即信號的參數類型和參數個數 同接收該信號的槽的參數類型和參數個數相同。不過一個槽的參數個數是能夠少於信號的參數的個數的,可是缺乏的參數必須是信號參數的最後一個或者幾個參數。若是信號和槽的簽名不符,編譯器就會報錯。
信號和槽機制大大下降了Qt對象的耦合度。發送信號的Qt對象不須要知道是哪一個對象來接收它的信號,它只須要作的是在適當的時間發送一個信號,並且不須要知道也不關心它的信號有沒有被接收到,更不須要知道哪一個對象的哪一個槽接收到了信號。
一樣地,Qt對象的槽也不須要關係是哪些信號鏈接了本身,若是信號和槽鏈接上了,Qt就能保證了適合的槽獲得了調用。即便關聯的對象在運行時被刪除。應用程序也不會崩潰。
信號和槽機制加強了對象間通訊的靈活性,固然在增長靈活性的同時在性能方面也會有必定的損失。同你們回調函數相比,信號和槽機制運行速度有些慢。一般,經過傳遞一個信號來調用槽函數將會比直接調用直接調用非虛函數運行速度慢10倍。
緣由:
然而,與建立堆對象的new操做及刪除堆對象的delete操做相比,信號和槽的運行代價只是它們不多一部分。信號和槽機制致使的這點性能損耗,對實時應用程序是能夠忽略的;同信號和槽提供的靈活性和簡便性相比,這點性能損耗是值得的。
做爲一名 iOS 開發人員, 見證着 iOS 佈局系統的不斷完善, 從絕對佈局, Autoresizing 到 Autolayout. 使得開發人員的工做效率愈來愈高, 項目界面的可讀性和易維護性愈來愈強. 現在 IDE 中的可視化界面工具已經很是強大, 許多網友"戲稱" iOS 開發者爲"UI 拖拽師", 可見, iOS 開發中界面佈局系統的高效. 因此, 優秀的佈局系統的使命在於讓開發者花更少的時間來完成更易維護的界面.
一樣的, 在 Qt 中, 系統提供了強大的排版機制來爲窗口中的視圖進行佈局排版, 通過了對 Qt 佈局一個初步的探索, 不得不對 Qt 佈局系統的簡潔高效而又功能強大表示讚歎.
在 Qt 中, 佈局系統能夠完成
Qt 提供了 QLayout 類及其子類來爲界面進行排版佈局. 結構以下圖:
QLayout 是佈局系統中的抽象基類, 繼承自 QObject 和 QLayoutItem, 其中四個子類分別爲
在真實使用場景中, 每每須要經過多種佈局的相結合來完成界面的設計, 接下來將分別介紹四中佈局.
箱式佈局提供了兩個子類分別處理水平(QHBoxLayout)和垂直(QVBoxLayout)兩個方向的排版, 可使視圖排成一行或者一列來顯示. 簡單說, 就是可讓控件進行排排站, 好比在咱們的 AlphaBox 中, 頂部的頭像, 姓名, 和刷新按鈕排成了一排, 這就是水平箱式佈局:
你覺得我要講一下這個東西如何實現? NO, 我恰恰要以垂直箱式佈局爲例, 用一個最簡單的例子來介紹箱式佈局的使用, 首先建立一個基於 QWidget 的界面, 添加咱們須要使用的頭文件:
#include <QVBoxLayout>
#include <QPushButton>
複製代碼
並在構造函數中添加以下代碼
// 添加兩個按鈕
QPushButton *okBtn = new QPushButton;
okBtn ->setText(tr("我在上面, 我最牛"));
QPushButton *celBtn = new QPushButton;
celBtn->setText(tr("我在下面, 我不服"));
// 建立一個垂直箱式佈局, 將兩個按鈕扔進去
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(okBtn);
layout->addWidget(celBtn);
// 設置界面的佈局爲垂直箱式佈局
setLayout(layout);
複製代碼
運行看一下效果, 什麼? 這就能夠運行了? 座標呢? 尺寸呢? 是的, 沒看錯...點擊運行:
兩個按鈕已經一上一下, 乖乖的在垂直方向本身站好了位置, 就是這麼強大, 就是這麼省心.
強大的 AlphaBox 是很外向的, 能夠很輕鬆的將你的資料分享給其餘用戶, 當咱們分享的時候, 會有這樣一個界面:
看到這個界面, 聰明的你可能會說, 這很簡單啊, 好幾個水平箱式佈局就能夠實現, 但是, 更聰明的 Qt 提供了更高效的方式幫助你完成這樣一個界面, 那就是 QFormLayout.
在我所學習 Qt 所使用的書籍中, 將 QFormLayout 翻譯爲窗體佈局, 我我的認爲, 將其翻譯爲表單佈局更爲貼切, 由於 QFormLayout 的強大之處正是可使用最快的速度完成一個用戶輸入的表單界面的搭建.
那麼, 讓咱們揭開 AlphaBox 的神祕面紗, 看看這樣一個界面是怎麼實現的.
首先, 拖拽一個 Form Layout 到 Widget 中.
雙擊以後便可爲表單增長一行.
相信你們看到這張圖時, 就已經能理解到表單佈局是如何使用的, 提供了標籤做爲用戶輸入內容的指引, 提供字段類型做爲用戶輸入的控件, 做爲 iOS 開發者, 深知這樣一個界面的搭建所須要的繁雜的工做量. 當我第一次打開這個界面時, 被這樣建立界面的方式所驚呆了.
快不快? 快不快! 快不快!!!
一樣的, 若是是使用純代碼表單佈局的話可使用addRow()
的方法來添加一行.
事實上, 強大的 AlphaBox 是這樣的, 咱們能夠共享給多個用戶, 並且, 下方會有一個列表, 展現共享的用戶以及權限列表. 這時, 表單佈局就沒辦法知足咱們, 只好另求新歡 QGridLayout - 網格佈局.
網格佈局顧名思義, 能夠將界面分割成行列來進行佈局管理, 在每一個單元格中來擺放控件. 因此 AlphaBox 分享的界面使用了一個 兩行三列 的網格佈局來實現的.
固然, 更更復雜的界面, 用 Qt 佈局的效率也是很是高的, 我作了一個外鏈分享的佈局 Demo, 能夠將內部資料生成一個下載連接共享給任何人去下載.
這個界面中, 我在Tab以內使用了網格佈局, 佈局如圖:
從圖中能夠看出, 網格佈局像是在操做一個 Excel 同樣簡單, 佈局單元格, 合併單元格, 等等.
在這個界面中, 更靈活的使用了 QLayout 的屬性來完成了界面佈局排版.
一樣的, 在代碼中, 可使用以下等的 Api 來爲網格視圖添加一個從幾行幾列開始佔據幾行幾列的控件:
void addWidget(QWidget *, int row, int column, int rowSpan, int columnSpan) 複製代碼
如在 AlphaBox 中, 咱們能夠經過雲端文件瀏覽器直接查看和操做雲端文件, 在加載的過程當中, 會有一個轉菊花的界面.
加載失敗時的錯誤提示:
以及加載成功時:
一般應用的界面會根據不一樣的狀態有不一樣的內容, 這時就可使用 QStackedLayout 棧佈局, 棧佈局提供了一個頁面的棧, 每一個頁面有徹底獨立的界面佈局. 能夠很是清晰的對不一樣狀態下的界面進行佈局管理.
在 Qt 的可視化佈局工具中, 經過 Stacked Widget 來完成界面的棧佈局
經過右鍵來進行頁面的插入移除和排序等操做.
在接下來的文章中咱們會從搭建項目起,分模塊的更加深刻的介紹Qt開發,敬請期待!