第四章 简单计算器程序
4.2 程序分析
本程序主要代码部分集中在CalculatorDialog类当中,本节里我们着重介绍一下类里的一些功能点。
首先在CalculatorMain.h中我们可以找到主要功能函数有:
void Init(); //程序初始化
void SwitchControlPad(bool enable); //遍历修改按钮可用状态
static wxString GetResultTxt(double result); //生成用来显示的结果
void Input(wxString num); //数字的输入
void SetOperator(int p); //运算符的输入
void Run(); //运算过程
然后还有很多事件处理函数:
//(*Handlers(CalculatorDialog)
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
void OnInit(wxInitDialogEvent& event);
……
void OnrdoDecSelect(wxCommandEvent& event);
void OnrdoHexSelect(wxCommandEvent& event);
void OnrdoOctSelect(wxCommandEvent& event);
//*)
最后我们根据本章一开始所提到的知识点,对功能函数中几个比较典型的地方进行一些说明。
4.2.1事件处理
功能函数我们很好理解,就是完成一定的功能的程序过程。但事件处理在wxWidgets里是怎么回事呢?这些事件处理函数通过什么来与具体的事件对应的呢?那其实这些在CalculatorMain.cpp中的构造函数中就可以找到答案。我们来仔细看一下CalculatorMain.cpp的构造函数CalculatorDialog::CalculatorDialog(wxWindow* parent,wxWindowID id)的后面一部分:
Connect(ID_RADIODEC,wxEVT_COMMAND_RADIOBUTTON_SELECTED,(wxObjectEventFunction)&CalculatorDialog::OnrdoDecSelect);
Connect(ID_RADIOHEX,wxEVT_COMMAND_RADIOBUTTON_SELECTED,(wxObjectEventFunction)&CalculatorDialog::OnrdoHexSelect);
……
Connect(ID_BTNEQUAL,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&CalculatorDialog::OnbtnEqualClick);
Connect(wxID_ANY,wxEVT_INIT_DIALOG,(wxObjectEventFunction)&CalculatorDialog::OnInit);
通过上面的代码,我们可以很清楚的看到,通过wxWidgets的Connect函数,就可以完成事件与处理函数的绑定和连接了,具体就拿第一条来分析:
Connect(ID_RADIODEC,wxEVT_COMMAND_RADIOBUTTON_SELECTED,(wxObjectEventFunction)&CalculatorDialog::OnrdoDecSelect);
第一个参数ID_RADIODEC——控件的资源ID号
第二个参数wxEVT_COMMAND_RADIOBUTTON_SELECTED——事件名
第三个参数CalculatorDialog::OnrdoDecSelect——事件要绑定的事件处理函数
由些可知,这一句意思就是把ID_RADIODEC(即界面上的DEC单选框)的被选中的事件,绑定到CalculatorDialog的OnrdoDecSelect函数中去处理。
通过上面的解释,大家应该明白了吧?至于什么样的控件有什么样的事件,大家可以查询官方API文档(在线地址:http://docs.wxwidgets.org/trunk/)。
另外,事件绑定还可以通过事件宏的方法可以实现,那就是在BEGIN_EVENT_TABLE中进行事件声明,比如说上面的第一条Connect改成这种方法就应该写成:
BEGIN_EVENT_TABLE(CalculatorDialog,wxDialog)
EVT_RADIOBUTTON(ID_RADIODEC, OnrdoDecSelect)
END_EVENT_TABLE()
关于各种事件所对应的事件处理宏写法,可以在API手册中的wxCommandEvent Class Reference篇里找到。
4.2.2 wxString的使用
在这个程序里对于wxString的使用,体现在如何实现计算器显示屏用到的字符和运算用的数字之间的转换,这些转换主要体现在功能函数Input()和GetResultTxt()当中,其中前者负责把字符转成数字,而后者负责把数字转成字符。
字符转数字(通过wxAtof、wxAtoi、wxAtol等函数):
this->m_nCurNum=wxAtof(this->txtResult->GetValue()); //这里我们转的是double
数字转字符(通过Format函数,与C++的String一样):
wxString resultstr=wxString::Format("%.13f",result); //保留13位小数
这两个函数除了进行字符和数字的互转,还涉及到字符的查找:
resultstr.Find('0',true)
字符的截取:
resultstr=resultstr.Left(resultstr.Len()-1);
等等。
若想知道关于wxString的更多详细的操作方法,请大家在官方API文档的wxString Class Reference篇进行查询。
4.2.3 控件遍历
我们在对界面进行编程时,经常会涉及到控件的状态变更,而更多的时候我们会将控件进行分组,然后通过遍历的方式来进行实现这个功能。在wxWidget里,我们同样可以这样来对控件进行操作。
在这个计算器程序中,当我们选中以八进制和十六进制显示计算结果的时候,我们将不允许用户输入,所以,当我们按下界面上的Hex或Oct这两个wxRadioButton控件时,我们需要遍历禁止掉输入面板上的按钮,而在我们再选回Dec控件时,我们再次启用输入面板上的按钮。这个禁止和启用的功能,我把它写在了SwitchControlPad()函数,其中一个参数是用来告诉它到底该禁止还是该启用。
void SwitchControlPad(bool enable)
{
wxWindowList controls = this->plControlPanel->GetChildren();
wxWindowList::iterator iter;
for (iter = controls.begin(); iter != controls.end(); ++iter)
{
wxWindow *button = *iter;
if(button!=NULL) button->Enable(enable);
}
}
通过上面的代码,我们可以看到要进行控件的遍历,需要用到wxWindowList容器对象,因为我们事先已经把需要遍历的按钮,都放在了一个统一的名为plControlPanel的wxPanel控件中,所以我们只要通过调用plControlPanel的GetChildren()函数,把获取的子控件存放在wxWindowList容器中,然后就可以通过wxWindowList的遍历方法实现遍历了。整个遍历过程十分简单,就是通过一个游标对象,从头到尾依次读取的顺序过程,相信有一定编程经验的都很容易掌握。
除特别声明为转载内容外,本站所有内容均为作者原创,谢绝任何单位和个人不经许可的复制和转播!
对于确有转载需要的,请先与作者联系,在获得允许后烦请在转载时保留文章出处。
本文出自Lupin's Blog:http://www.cnzui.com/archives/982
老师,我打开工程后,基本全都报错,不知为什么?用wxWidgets2.8,CodeBlocks10.5 不知有没有影响。
呵呵,sam你好,老师这个称呼太大了承受不起啊,大家互相学习吧!这个工程是基于wxWidgets2.9.4的,直接用在wxWidgets2.8里肯定不行的,但你可以稍微修改一下就该就好了,像字符串的定义2.9里可以直接定义为””,而2.8里必须要定义为wxT(“Hello World”)。
尛龖龘老师,可能是我的软件搭建还不完整,不知为什么,用wxWidgets2.9.4编译不了,只是装了wxPack_v2.8.12.01.exe,感觉问题还很多。能加您的QQ吗,可以截图看看问题出在哪里,我的Q343366680 ,多谢!
我已经加了你的QQ了,你可以先看看教程的前几章,或许你就能找到答案了。
尛龖龘老师 Q657148190 也加下我的扣扣吧 wxWidgets连接SQLServer,好久了,还没找到头绪。。。
请问源代码在哪儿呀?
老师你好,我现在的软件需要再屏幕上显示上万行的字符串,使用wxTextCtrl控件的WriteText()添加并显示,但是wxTextCtrl的显示数目有限,导致怎么软件死掉,请问有什么办法解决,我的QQ是415113970,多谢!