wxWidgets

wxWidgets

wxWidgets是一個開源的跨平台的C++構架庫(framework),它可以提供GUI(圖形用戶界面)和其它工具。目前的2.x版本支持所有版本的Windows、帶GTK+或Motif的Unix和MacOS。一個支持OS/2的版本正在開發中。

起源

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檔案 再編譯。

使用wxWidgets開發的程式有很多,比較著名的有跨平台3D遊戲0.A.D, 集成編程工具Code::Blocks和CodeLite,檔案傳輸工具filezilla。

類似於Qt的QtDesigner界面編譯器,wxWidgets也有相應的界面開發工具,如wxSmith和wxFormBuilder,有著非常友好人機互動界面,實現界面可視化開發。

程式示例

下面的例子來源於wxWidgets的官方文檔,實現最簡單的Hello World程式。

wxWidgets wxWidgets
wxWidgets wxWidgets

// 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();

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!");

}

相關詞條

相關搜尋

熱門詞條

聯絡我們