wxWidgets是一個開源的跨平臺的C++構(gòu)架庫(framework),它可以提供GUI(圖形用戶界面)和其它工具。目前的2.x版本支持所有版本的Windows、帶GTK+或Motif的Unix和Mac OS。一個支持OS/2的版本正在開發(fā)中。
起源
wxWidgets在最開始是由愛丁堡(愛丁堡)大學(xué)的人工智能應(yīng)用學(xué)院開發(fā)的,主要是內(nèi)部使用,而在1992年第一次公布。 2.x版本做了很大程度的改良,并且由Julian Smart, Robert 無限法則bling, Vadim Zeitlin, Vaclav Slavik和更多其他的人所編寫和維護。
wxWidgets的主體是由C++構(gòu)建的,但你并不是必需通過C++才能使用wxWidgets.wxWidgets擁有許多其它語言的綁定(binding),使你在用其它語言編寫程序的時候也可以使用wxWidgets.
* wxPython a Python binding,
* wxPerl a Perl binding,
* wxBasic a Basic binding,
* wxLua a Lua binding,
* wxECMAScript a JavaScript binding,
* wxJava a Java binding by Steve Perkins,
* wx4j a Java binding by Dave Dribin,
* wxRuby a Ruby binding,
* wxEiffel an Eiffel binding,
* wxHaskell a Haskell binding,
* wxEuphoria a Euphoria binding,
* wxN-(2-乙酰氨基)-亞氨基二醋酸 the start of an Ada binding for wxWidgets.
wxwidgets是一個 C++編寫的用來提供gui開發(fā)的框架。它包含一個可以支持現(xiàn)今幾乎所有操作系統(tǒng)(Version 2 currently supports all desktop versions of MS Windows, Unix with GTK+, Unix with Motif, and MacOS. An OS/2 port is in progress.)的GUI庫和其他一些很有用的工具,提供了類似mfc的功能。而且,特別要說一下,這個C++天秤座的新版本還提供了對掌上電腦的支持。當(dāng)然,說到這里很多人會想到j(luò)ava對多系統(tǒng)的支持,其實這是不一樣的,java的跨平臺是建立在“中間代碼”的基礎(chǔ)上的,就是說需要在目標平臺上安裝java解釋器;但是wxwidgets是C++庫,經(jīng)過編譯后,他提供的是native級的機器碼,在gui編程方面,這可是意味著很大的不同。
優(yōu)勢
那么wxwidgets有什么特別之處呢?比起其他的跨平臺gui庫,有什么好處呢?
1、就是他無論對于個人還是對于商業(yè)應(yīng)用都是免費的!
——它的主體框架的授權(quán)協(xié)議支持商業(yè)免費應(yīng)用,其外圍功能庫中很多也是lgpl授權(quán)的,這無疑對于我等“0資本”的人來說是天大的好事。不同于Qt之類的跨平臺gui庫。
2、他是跨平臺的gui庫,支持的操作系統(tǒng)很全面,甚至支持pda(最新版本【3.0.1】支持iOS,可以在下載的源碼包中找到wxWidgets-3.0.1.tar.bz2\wxWidgets-3.0.1\build\osx\wxIPhonexcodeproj)。
—— 此跨平臺非彼跨平臺,它雖然不像java那樣是“全面”的,而僅僅是gui庫,但是gui是計算機編程中,最為麻煩、耗費時間、容易出現(xiàn)bug的部分,特別當(dāng)你想要自己的軟件運行在多個操作系統(tǒng)上的時候,開發(fā)和維護的難度讓人難以想象。其實C++也是支持“跨平臺”的,因為c++可以在任何平臺上編譯運行,之所以沒幾個人說他是跨平臺的,主要問題就出在變量長度和各操作系統(tǒng)的gui(這里的“界面”我指得是很廣義的)上,如果解決了gui的問題,基本上就解決了c++的“跨平臺”問題——至少不用為每種平臺都維護一份源代碼了。
3、 wxwidgets提供的gui是大量使用宏的,這就意味著它是在盡可能的使用目標系統(tǒng)native的gui樣式。
——你可以訪問wxwidgets網(wǎng)站,看看那些開發(fā)的軟件的截圖,全是系統(tǒng)native級別的。如果你開發(fā)了一個Windows XP的軟件的話,你的軟件會仍然以“xp專有的‘小賤人’級別”的面貌展現(xiàn)在你面前。
4、它支持的編譯器也很多,而且Borland也曾聲明將在c++builderx2里邊提供對wxidgets的支持——預(yù)覽版都出來了。
——其實我就是看到borland在C++不景氣的時候,這么看重這個東東,甚至用它來做“王牌”,才開始注意到他的。當(dāng)然,反過來,也正是borland的支持,才使他活力大發(fā)的。
5、自然,有牛X支持,而且是開源的,wxWidgets一直都在快速穩(wěn)健的開發(fā)中,其周邊工具也越來越多。
—— 隨著MS開始全力支持他的.net,C++成了“沒落”的語言,但是不可否認,c++還是有很多用武之地的,所以根本不可能真正沒落。沒有了超牛X的支持,地球人自然開始尋求新的發(fā)展方式,wxWidgets這種開源免費,且允許商業(yè)應(yīng)用的好東東,自然會被人們所重視。
事件處理機制
類似于mfc的MESSAGE_MAP,wxWidgets使用EVENT_TABLE語法糖實現(xiàn)對事件處理函數(shù)的回調(diào)。具體的實現(xiàn)方法是,在h文件的類聲明里添加宏
wxDECLARE_EVENT_TABLE()
并在cpp文件里面添加對應(yīng)事件處理函數(shù)的列表:
wxBegin_EVENT_TABLE(..., ...)
EVT_MENU(..., ...)//菜單事件
EVT_BTN(..., ...)//按鈕事件
EVT_PAINT(...)//繪圖事件
EVT_LBUTTON_DOWN(...)//鼠標事件
EVT_KEY_DOWN(...)//鍵盤事件
......
wxEND_EVENT_TABLE()
其中宏wxDECLARE_EVENT_TABLE()有兩個參數(shù),第一個是自定義的類名,第二個是派生類的基類名。而里面事件處理函數(shù)的列表中,不同的處理事件對應(yīng)的宏參數(shù)不同。通常情況下,像菜單、按鈕這樣可能由不同控件觸發(fā)的事件,對應(yīng)的宏有兩個參數(shù),第一個參數(shù)為控件的ID,第二個參數(shù)為事件處理函數(shù)的指針。而像繪圖,鼠標,鍵盤這樣的可以由不同硬件觸發(fā)或者觸發(fā)來源單一的事件,則有一個參數(shù),即為事件處理函數(shù)的指針。
程序結(jié)構(gòu)
wxWidgets程序封裝了main函數(shù)和消息循環(huán)。通常情況下,整個程序通過繼承wxApp類并用全局宏wxIMPLEMENT_APP,傳入wxApp的派生類的類名實現(xiàn)對類的實例化并進入消息循環(huán)。
在進入消息循環(huán)之前,創(chuàng)建主窗口的工作通過在wxApp的派生類中重新實現(xiàn)wxApp的虛函數(shù)OnInit來完成。主窗口通常是wxFrame或wxDIALOG的派生類,其中的控件都作為主窗口類的成員變量,在主窗口類的構(gòu)造函數(shù)中初始化。
從中可以看出,wxWidgets在程序結(jié)構(gòu)方面與mfc也有很大的相似之處。
前景
當(dāng)然,wxWidgets也有一些不足,比如官方文檔不全,對STL的支持不夠,特別是沒有源代碼的開發(fā)速度快;沒有強大全面的rad工具;還沒有形成很濃的產(chǎn)業(yè)氣候,等等。但是,個人覺得它的好處絕對大于它的缺點,而且很有發(fā)展前途。
相比MFC,wxWidgets有著跨平臺和開源免費的優(yōu)勢;相比Qt,wxWidgets的語法是完全C++的,不像Qt的Q_OBJECT宏需要用moc單獨編譯出一個cpp文件再編譯。
使用wxWidgets開發(fā)的程序有很多,比較著名的有跨平臺3D游戲0.A.D, 集成編程工具Code::Blocks和CodeLite,文件傳輸工具filezilla。
類似于Qt的QtDesigner界面編譯器,wxWidgets也有相應(yīng)的界面開發(fā)工具,如wxSmith和wxFormBuilder,有著非常友好人機交互界面,實現(xiàn)界面可視化開發(fā)。
程序示例
下面的例子來源于wxWidgets的官方文檔,實現(xiàn)最簡單的Hello World程序。
// wxWidgets "Hello world" Program
// For compilers that support precompilation, includes "wx/wx.h".
#include
#ifndef WX_PRECOMP
#include
#endif
class MyApp: public wxApp //這個類用來實現(xiàn)全局消息循環(huán)
{public:
virtual bool OnInit(); //在進入消息循環(huán)之前調(diào)用此函數(shù)實現(xiàn)對主窗口類的初始化};
class MyFrame: public wxFrame //主窗口類
{public:
MyFrame(const wxString& title, const wxPoint& pos, const wxSize& 開本);
private:
void OnHello(wxCommandEvent& event);
void OnExit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
wxDECLARE_EVENT_TABLE();};
enum
{ID_Hello = 1};
wxBegin_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(ID_Hello, MyFrame::OnHello)
EVT_MENU(wxID_EXIT, MyFrame::OnExit)
EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
wxEND_EVENT_TABLE()
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
{MyFrame *車架 = new MyFrame( "Hello World", wxPoint(50, 50), wxSize(450, 340) );
frame->Show( true );
回車鍵 true;}
MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& 開本)
: wxFrame(NULL, wxID_ANY, title, pos, size)
{wxMenu *menuFile = new wxMenu;
menuFile->Append(ID_Hello, "&Hello...\tCtrl-H",
"Help string shown in status bar for this menu item");
menuFile->AppendSeparator();
menuFile->Append(wxID_EXIT);
wxMenu *menuHelp = new wxMenu;
menuHelp->Append(wxID_ABOUT);
wxMenubar *menuBar = new wxMenuBar;
menubar>Append( menuFile, "&File" );
menuBar->Append( menuHelp, "&Help" );
SetMenuBar( menuBar );
createStatusBar();
SetStatusText( "Welcome to wxWidgets!" );}
void MyFrame::OnExit(wxCommandEvent& event)
{Close( true );}
void MyFrame::OnAbout(wxCommandEvent& event)
{wxMessageBox( "This is a wxWidgets' Hello world sample",
"About Hello World", wxOK | wxICON_INFORMATION );}
void MyFrame::OnHello(wxCommandEvent& event)
{wxLogMessage("Hello world from wxWidgets!");}
參考資料 >