wxwidgets学习笔记——在Frame上显示时间,实现能够定时刷新的时钟

来源:互联网 发布:镜片折射率知乎 编辑:程序博客网 时间:2024/06/02 01:01

想在Frame窗口上显示时钟信息,因为没有系统的学习wxwidgets,自己想了一种最笨的方案,见笑。

 

一、实现方案:

1、原始方案:

用wxDateTime获取当前的时间,赋给一个wxString类的参数。但是如果只采用DrawText写文本,第二次之后就会覆盖前一次的文本。

2、改进后的方案:

先用DrawRectangle画一个确定大小、确定位置的矩形框,再用DrawText写文本,将上述操作封装进入OnTimer中,用wxTimer类的实例来定时触发wxTimerEvent后调用OnTimer,就能实现不停的刷新时间。

二、关于wxTimer的使用:

wxTimer类允许使用者以特定的间隔时间执行代码。其实现原理是计数器记满预设的时间之后会触发事件wxTimerEvent,触发事件EVT_TIMER调用OnTimer,在OnTimer函数中可以写入你想要周期性执行的代码。

成员函数:wxTimer (wxEvtHandler *owner, int id=-1)用于创建一个计数器timer并将其链接到一个拥有者owner,id是这个计数器timer的标示符,用于事件宏EVT_TIMER中用于区分不同的timer。

使用时主要在所在类(这个类要求直接或者间接继承自wxEvtHandler)的构造函数(如ShapedFrame)添加(new)一个wxTimer的指针(如m_timer),然后调用成员函数Start (int milliseconds=-1, bool oneShot=false)启动计时x微秒的计数器。

 

三、代码节选:

 

//定义继承自基类wxFrame的 ShapedFrame 类class ShapedFrame : public wxFrame {public:    // ctor(s)        ShapedFrame();    void SetWindowShape();    void OnTimer(wxTimerEvent& event);private:        // 把 wxTimer作为  ShapedFrame的成员     wxTimer *m_timer;}

 

本来想这样写class ShapedFrame : public wxFrame,public wxTimer,想让类ShapedFrame继承两种基类,不过行不通,只能像上面的代码一样将wxTimer定义成一个具体的参数,然后再之后的构造函数中创建(new)。

 

#define TIMER_ID 1000 BEGIN_EVENT_TABLE(ShapedFrame, wxFrame) EVT_TIMER(TIMER_ID, ShapedFrame::OnTimer) END_EVENT_TABLE()

 

以上是事件列表,用于连接时间和具体调用的函数。
 

//ShapedFrame的构造函数 ShapedFrame::ShapedFrame()       : wxFrame((wxFrame *)NULL, wxID_ANY, wxEmptyString,     //里面的参数定义可以无视                  wxDefaultPosition, wxSize(100, 100), //wxDefaultSize,                  0                  | wxFRAME_SHAPED                  | wxSIMPLE_BORDER                  | wxFRAME_NO_TASKBAR                  | wxSTAY_ON_TOP            ){// 新建一个wxTimer 类的指针m_timer    wxTimer *m_timer = new wxTimer(this,TIMER_ID);            m_timer->Start(1000); //开始定时计数,定时时间是1s,也就是每秒调用一次OnTimer }


 

void ShapedFrame::OnTimer(wxTimerEvent& event) {         wxString buf;    long chw, chh;        wxClientDC dc(this);   //设置句柄         //获取当前时间     wxDateTime time = wxDateTime::Now();          int h = time.GetHour();      int m = time.GetMinute();      int s = time.GetSecond();          wxString title;    title.Printf("Clock %i:%.2i:%.2i", h, m, s);   // buf = wxT("M");        dc.SetBrush(*wxLIGHT_GREY_BRUSH);         dc.DrawRectangle( 110,10,120,20);     // 画个矩形填充颜色         dc.SetTextForeground(*wxBLACK);      // 写时间     dc.GetTextExtent(title, &chw, &chh); // buf    dc.DrawText(title,110,10);      // buf    // dc->DrawText(title,110,10)报错:    //base operand of `->' has non-pointer type `wxClientDC'    //  因为dc不是指针 }


四、效果图:

就截个部分Frame的图,丑陋成一把刀了,凑合能一秒一秒的刷新,和电子钟似的:




2011年10月11日补充:

五、另一种方法

用wx静态文本控件wxStaticText来显示时间,wxStaticText的功能是显示文本,并含有成员函数SetLabel用以更新文本

具体操作如下:

首先在Frame函数的构造函数中添加一个wxStaticText控件:

TimeText = new wxStaticText( panel1, wxID_ANY, title , wxDefaultPosition, wxDefaultSize, 0 );


其中title就是已经赋值了当前时间的wxString参数,在控件创建的时候就显示当前时间,如果将title换成wxT(“”)就会出现一开始的瞬间内容为空的效果,这样不太美观;


当然还要在定义Frame函数的时候声明空间名称:如:wxStaticText* TempText;


然后就和之前的操作一样,唯一要改动的就是OnTimer内部的函数了,将title赋值完毕之后,写一句

 TimeText->SetLabel(title);

就大功告成了。


当然如果你想设置一下字体,也是很方便的,可以仿造下面的样子在SetLable之后加一句:

TimeText->SetFont( wxFont( 26, 74, 90, 90, false, wxT("Calibri") ) );
表示采用某种大小的某种字体。


奉上截图: