起源
wxWidgets在最開始是由
愛丁堡(Edinburgh)大學的
人工智慧套用學院開發的,主要是內部使用,而在1992年第一次公布。 2.x版本做了很大程度的改良,並且由Julian Smart, Robert Roebling, Vadim Zeitlin, Vaclav Slavik和更多其他的人所編寫和維護。
wxWidgets的主體是由
C++構建的,但你並不是必需通過C++才能使用wxWidgets.wxWidgets擁有許多其它語言的綁定(binding),使你在用其它語言編寫程式的時候也可以使用wxWidgets.
* wxPython a Python binding,
* wxPerl a Perl binding,
* wxBasic a Basic binding,
* wxLua a Lua binding,
* wxJavaScript 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,
* wxAda the start of an Ada binding for wxWidgets.
wxwidgets是一個
c++編寫的用來提供
gui開發的框架。它包含一個可以支持現今幾乎所有作業系統(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++lib的新版本還提供了對
掌上電腦的支持。當然,說到這裡很多人會想到java對
多系統的支持,其實這是不一樣的,java的跨平台是建立在“
中間代碼”的基礎上的,就是說需要在目標平台上安裝java
解釋器;但是wxwidgets是
c++庫,經過編譯後,他提供的是native級的
機器碼,在
gui編程方面,這可是意味著很大的不同。
優勢
那么wxwidgets有什麼特別之處呢?比起其他的跨平台
gui庫,有什麼好處呢?
1、就是他無論對於個人還是對於商業套用都是免費的!
——它的主體框架的授權協定支持商業免費套用,其外圍功能庫中很多也是lgpl授權的,這無疑對於我等“0資本”的人來說是天大的好事。不同於Qt之類的跨平台gui庫。
2、 他是跨平台的gui庫,支持的作業系統很全面,甚至支持pda(最新版本【3.0.1】支持iOS,可以在下載的源碼包中找到wxWidgets-3.0.1.tar.bz2\wxWidgets-3.0.1\build\osx\wxiphone.xcodeproj)。
—— 此跨平台非彼跨平台,它雖然不像java那樣是“全面”的,而僅僅是
gui庫,但是gui是計算機編程中,最為麻煩、耗費時間、容易出現bug的部分,特別當你想要自己的軟體運行在多個作業系統上的時候,開發和維護的難度讓人難以想像。其實
c++也是支持“跨平台”的,因為c++可以在任何平台上編譯運行,之所以沒幾個人說他是跨平台的,主要問題就出在變數長度和各作業系統的
gui(這裡的“界面”我指得是很廣義的)上,如果解決了gui的問題,基本上就解決了c++的“跨平台”問題——至少不用為每種平台都維護一份
原始碼了。
3、 wxwidgets提供的gui是大量使用宏的,這就意味著它是在儘可能的使用目標系統native的gui樣式。
——你可以訪問wxwidgets網站,看看那些開發的軟體的截圖,全是系統native級別的。如果你開發了一個xp系統的軟體的話,你的軟體會仍然以“xp專有的‘小賤人’級別”的面貌展現在你面前。
4、 它支持的
編譯器也很多,而且borland也曾聲明將在
c++builderx2裡邊提供對wxidgets的支持——預覽版都出來了。
——其實我就是看到borland在c++不景氣的時候,這么看重這個東東,甚至用它來做“王牌”,才開始注意到他的。當然,反過來,也正是borland的支持,才使他活力大發的。
5、 自然,有牛X支持,而且是開源的,wxWidgets一直都在快速穩健的開發中,其周邊工具也越來越多。
—— 隨著MS開始全力支持他的.net,c++成了“沒落”的語言,但是不可否認,c++還是有很多用武之地的,所以根本不可能真正沒落。沒有了超牛X的支持,地球人自然開始尋求新的發展方式,wxWidgets這種開源免費,且允許商業套用的好東東,自然會被人們所重視。
事件處理機制
類似於MFC的MESSAGE_MAP,wxWidgets使用EVENT_TABLE
語法糖實現對事件處理函式的回調。具體的實現方法是,在h檔案的類聲明里添加宏
wxDECLARE_EVENT_TABLE()
並在cpp檔案裡面添加對應事件處理函式的列表:
wxBEGIN_EVENT_TABLE(..., ...)
EVT_MENU(..., ...)//選單事件
EVT_BTN(..., ...)//按鈕事件
EVT_PAINT(...)//繪圖事件
EVT_LBUTTON_DOWN(...)//滑鼠事件
EVT_KEY_DOWN(...)//鍵盤事件
......
wxEND_EVENT_TABLE()
其中宏wxDECLARE_EVENT_TABLE()有兩個參數,第一個是自定義的類名,第二個是派生類的基類名。而裡面事件處理函式的列表中,不同的處理事件對應的宏參數不同。通常情況下,像選單、按鈕這樣可能由不同控制項觸發的事件,對應的宏有兩個參數,第一個參數為控制項的ID,第二個參數為事件處理函式的指針。而像繪圖,滑鼠,鍵盤這樣的可以由不同硬體觸發或者觸發來源單一的事件,則有一個參數,即為事件處理函式的指針。
程式結構
wxWidgets程式封裝了main函式和訊息循環。通常情況下,整個程式通過繼承wxApp類並用全局宏wxIMPLEMENT_APP,傳入wxApp的派生類的類名實現對類的實例化並進入訊息循環。
在進入訊息循環之前,創建主視窗的工作通過在wxApp的派生類中重新實現wxApp的虛函式OnInit來完成。主視窗通常是wxFrame或wxDialog的派生類,其中的控制項都作為主視窗類的成員變數,在主視窗類的構造函式中初始化。
從中可以看出,wxWidgets在程式結構方面與MFC也有很大的相似之處。
前景
當然,wxWidgets也有一些不足,比如官方文檔不全,對STL的支持不夠,特別是沒有
原始碼的開發速度快;沒有強大全面的rad工具;還沒有形成很濃的產業氣候,等等。但是,個人覺得它的好處絕對大於它的缺點,而且很有發展前途。
相比MFC,wxWidgets有著跨平台和開源免費的優勢;相比Qt,wxWidgets的語法是完全C++的,不像Qt的Q_OBJECT宏需要用moc單獨編譯出一個cpp檔案再編譯。
類似於Qt的QtDesigner界面編譯器,wxWidgets也有相應的界面開發工具,如wxSmith和wxFormBuilder,有著非常友好人機互動界面,實現界面可視化開發。
程式示例
下面的例子來源於wxWidgets的官方文檔,實現最簡單的Hello World程式。
// wxWidgets "Hello world" Program
// For compilers that support precompilation, includes "wx/wx.h".
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
class MyApp: public wxApp //這個類用來實現全局訊息循環
{
public:
virtual bool OnInit(); //在進入訊息循環之前調用此函式實現對主視窗類的初始化
};
class MyFrame: public wxFrame //主視窗類
{
public:
MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
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 *frame = new MyFrame( "Hello World", wxPoint(50, 50), wxSize(450, 340) );
frame->Show( true );
return true;
}
MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
: 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();
wxMenu *menuHelp = new wxMenu;
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!");
}