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

时间:2022-01-30 14:33:07

想在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的图,丑陋成一把刀了,凑合能一秒一秒的刷新,和电子钟似的:


wxwidgets学习笔记——在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") ) );
表示采用某种大小的某种字体。


奉上截图:

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


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


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