WxWidgets程序设计教程03:第一个程序
本章内容包含了创建wxWidgets应用程序所需的基本知识。我们将创建第一个简单的例子,用来展示如何显示一个图标。接着会创建一个用来示范事件的使用的例子。最后,我们来了解wxWidgets应用程序中的组件是如何进行通信的。
一个简单的应用程序
首先我们来创建一个非常基本的wxWidgets程序。
#include <wx/wx.h>
class Simple : public wxFrame
{
public:
Simple(const wxString& title);
};
#include "simple.h"
Simple::Simple(const wxString& title)
: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(250, 150))
{
Centre();
}
#include <wx/wx.h>
class MyApp : public wxApp
{
public:
virtual bool OnInit();
};
#include "main.h"
#include "simple.h"
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
Simple *simple = new Simple(wxT("Simple"));
simple->Show(true);
return true;
}
这个非常基础的例子在屏幕中显示了一个小窗口,窗口居中放置。
Centre();
该函数将窗口居中(包括水平合垂直方向)放置在屏幕上。
IMPLEMENT_APP(MyApp)
这个宏代码隐藏了程序实现的细节,通常我们没必要关注该代码的细节,复制粘贴即可。
Figure: Simple
显示应用程序图标
在这个例子中,我们为应用程序加了一个图标。按标准地在窗口的左上角上显示了个小图标。图标是程序的一个图形化标识。
#include <wx/wx.h>
class Icon : public wxFrame
{
public:
Icon(const wxString& title);
};
#include "icon.h"
Icon::Icon(const wxString& title)
: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(250, 150))
{
SetIcon(wxIcon(wxT("web.xpm")));
Centre();
}
#include <wx/wx.h>
class MyApp : public wxApp
{
public:
virtual bool OnInit();
};
#include "main.h"
#include "icon.h"
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
Icon *icon = new Icon(wxT("Icon"));
icon->Show(true);
return true;
}
在例子中我们要显示一个小的网页图标。
SetIcon(wxIcon(wxT("web.xpm")));
To display an application icon is a matter of one code line. XPM (X PixMap) is an ASCII image format.
Figure: Icon
简单的按钮
在下例中,要在框架组件上创建一个按钮。同时展示如何创建一个简单的事件句柄。
#include <wx/wx.h>
class Button : public wxFrame
{
public:
Button(const wxString& title);
void OnQuit(wxCommandEvent & event);
};
#include "button.h"
Button::Button(const wxString& title)
: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(270, 150))
{
wxPanel *panel = new wxPanel(this, wxID_ANY);
wxButton *button = new wxButton(panel, wxID_EXIT, wxT("Quit"),
wxPoint(20, 20));
Connect(wxID_EXIT, wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(Button::OnQuit));
button->SetFocus();
Centre();
}
void Button::OnQuit(wxCommandEvent & WXUNUSED(event))
{
Close(true);
}
#include <wx/wx.h>
class MyApp : public wxApp
{
public:
virtual bool OnInit();
};
#include "main.h"
#include "button.h"
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
Button *btnapp = new Button(wxT("Button"));
btnapp->Show(true);
return true;
}
wxPanel *panel = new wxPanel(this, wxID_ANY);
首先创建一个wxPanel组件。它被放在一个wxFrame组件内。
wxButton *button = new wxButton(panel, wxID_EXIT, wxT("Quit"), wxPoint(20, 20));
创建一个wxButton组件,它被放在面板之中。按钮的id使用预定义的wxID_EXIT,它将在按钮上显示一个小的退出图标。按钮上标注文字是"Quit"。按钮被手工放置在坐标点x=20, y=20上。坐标系的起始点为左上角。
Connect(wxID_EXIT, wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(Button::OnQuit));
如果点击按钮,就会产生一个wxEVT_COMMAND_BUTTON_CLICKED事件。我们将事件与Button类的OnQuit()方法相关联。因此点击按钮时,OnQuit()方法就会被调用。
button->SetFocus();
设置键盘焦点到按钮上。因此按下回车键,就相当于点击了按钮。
Close(true);
在OnQuit()方法中,调用了Close()方法。用来终止程序。
Figure: Button
组件间的通信
应用程序中的组件相互间是如何通信的,这点很重要。请看下面的例子。
#include <wx/wx.h>
#include <wx/panel.h>
class LeftPanel : public wxPanel
{
public:
LeftPanel(wxPanel *parent);
void OnPlus(wxCommandEvent & event);
void OnMinus(wxCommandEvent & event);
wxButton *m_plus;
wxButton *m_minus;
wxPanel *m_parent;
int count;
};
class RightPanel : public wxPanel
{
public:
RightPanel(wxPanel *parent);
void OnSetText(wxCommandEvent & event);
wxStaticText *m_text;
};
const int ID_PLUS = 101;
const int ID_MINUS = 102;
#include <wx/stattext.h>
#include "Communicate.h"
LeftPanel::LeftPanel(wxPanel * parent)
: wxPanel(parent, -1, wxPoint(-1, -1), wxSize(-1, -1), wxBORDER_SUNKEN)
{
count = 0;
m_parent = parent;
m_plus = new wxButton(this, ID_PLUS, wxT("+"),
wxPoint(10, 10));
m_minus = new wxButton(this, ID_MINUS, wxT("-"),
wxPoint(10, 60));
Connect(ID_PLUS, wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(LeftPanel::OnPlus));
Connect(ID_MINUS, wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(LeftPanel::OnMinus));
}
void LeftPanel::OnPlus(wxCommandEvent & WXUNUSED(event))
{
count++;
Communicate *comm = (Communicate *) m_parent->GetParent();
comm->m_rp->m_text->SetLabel(wxString::Format(wxT("%d"), count));
}
void LeftPanel::OnMinus(wxCommandEvent & WXUNUSED(event))
{
count--;
Communicate *comm = (Communicate *) m_parent->GetParent();
comm->m_rp->m_text->SetLabel(wxString::Format(wxT("%d"), count));
}
RightPanel::RightPanel(wxPanel * parent)
: wxPanel(parent, wxID_ANY, wxDefaultPosition,
wxSize(270, 150), wxBORDER_SUNKEN)
{
m_text = new wxStaticText(this, -1, wxT("0"), wxPoint(40, 60));
}
#include "Panels.h"
#include <wx/wxprec.h>
class Communicate : public wxFrame
{
public:
Communicate(const wxString& title);
LeftPanel *m_lp;
RightPanel *m_rp;
wxPanel *m_parent;
};
#include "Communicate.h"
Communicate::Communicate(const wxString& title)
: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(290, 150))
{
m_parent = new wxPanel(this, wxID_ANY);
wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL);
m_lp = new LeftPanel(m_parent);
m_rp = new RightPanel(m_parent);
hbox->Add(m_lp, 1, wxEXPAND | wxALL, 5);
hbox->Add(m_rp, 1, wxEXPAND | wxALL, 5);
m_parent->SetSizer(hbox);
this->Centre();
}
#include <wx/wx.h>
class MyApp : public wxApp
{
public:
virtual bool OnInit();
};
#include "main.h"
#include "Communicate.h"
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
Communicate *communicate = new Communicate(wxT("Widgets communicate"));
communicate->Show(true);
return true;
}
例子中有两个面板,一个左面板和一个右面板。左面板中有2个按钮。右面板则包含一个静态文本组件。按钮会改变静态文本组件中显示的数字。现在问题是,我们如何来获取指向静态文本组件的指针?
m_parent = parent;
这里将左面板父组件的指针保存起来,它是一个wxPanel组件。
Communicate *comm = (Communicate *) m_parent->GetParent();
comm->m_rp->m_text->SetLabel(wxString::Format(wxT("%d"), count));
这是例子中最重要的两行。它展示了,我们如何来访问在不同面板中的静态文本组件。首先获取左右面板的父组件,父组件有一个指向右面板的指针,而右面板有一个指向静态文本组件的指针。
Figure: Widgets communicate