[ZETCODE]wxWidgets教程八:組件專題1


本教程原文鏈接:http://zetcode.com/gui/wxwidgets/widgets/

翻譯:瓶哥

日期:2013年12月12日星期四

郵箱:414236069@qq.com

主頁:http://www.cnblogs.com/pingge/

若有翻譯錯誤或者歧義請聯系我!

 

在這一章中,我們將展示幾個關於控件的小例子,控件組成了我們的應用程序,wxWidgets中包含了大量有用的控件。控件被定義為一個GUI的基本對象,widget這個詞通常在UNIX系統上使用,在windows系統上一個控件通常被叫做control。

 

wxCheckBox

wxCheckBox是一個有兩個狀態的控件,選中/未選中。它看起來是一個選框和一個標簽,這個標簽可以被設置在選框的左邊或者右邊,如果這個選框被選中,在這選框中會有一個√標記,一個wxCheckBox可以用來控制在啟動時顯示或隱藏LOGO,顯示或隱藏一個工具欄,等等。

checkbox.h

#include <wx/wx.h>

class CheckBox : public wxFrame
{
public:
    CheckBox(const wxString & title);

    void OnToggle(wxCommandEvent & event);

    wxCheckBox * m_cb;

    enum{ID_CHECKBOX};
};

checkbox.cpp

#include "checkbox.h"

CheckBox::CheckBox(const wxString & title)
        : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(270, 150))
{
    wxPanel * panel = new wxPanel(this, wxID_ANY);

    m_cb = new wxCheckBox(panel, ID_CHECKBOX, _T("Show title"), wxPoint(200 / 2, 80 / 2));

    m_cb->SetValue(true);

    Connect(ID_CHECKBOX, wxEVT_COMMAND_CHECKBOX_CLICKED,
            wxCommandEventHandler(CheckBox::OnToggle));
    Centre();
}

void CheckBox::OnToggle(wxCommandEvent & WXUNUSED(event))
{
    if(m_cb->GetValue())
    {
        this->SetTitle(_T("CheckBox"));
    }
    else
    {
        this->SetTitle(_T(""));
    }
}

main.h

#include <wx/wx.h>

class MyApp : public wxApp
{
public:
    virtual bool OnInit();
};

main.cpp

#include "main.h"
#include "checkbox.h"

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{
    CheckBox * cb = new CheckBox(_T("CheckBox"));
    cb->Show(true);

    return true;
}

 

在我們的例子中,我們顯示了一個checkbox,我們通過這個選框來顯示或隱藏主窗口的標題。

m_cb = new wxCheckBox(panel, ID_CHECKBOX, _T("Show title"), wxPoint(200 / 2, 80 / 2));

m_cb->SetValue(true);

我們創建了一個checkbox,並調用SetValue()方法,設置默認為選中狀態。

Connect(ID_CHECKBOX, wxEVT_COMMAND_CHECKBOX_CLICKED,

wxCommandEventHandler(CheckBox::OnToggle));

如果我們點擊了這個選框,一個wxEVT_COMMAND_CHECKBOX_CLICKED事件產生,我們把這個事件同OnToggle()方法關聯起來。

if(m_cb->GetValue())

{this->SetTitle(_T("CheckBox"));

}

else

{this->SetTitle(_T(""));

}

在OnToggle()方法內,我們檢查了checkbox的狀態,如果是選中狀態,我們把標題設置為"CheckBox",如果是未選中,我們隱藏標題字符串。

 

wxBitmapButton

一個位圖按鈕是一個特殊的按鈕,它的主體是一張圖片。一個位圖按鈕上的圖片可以隨意設置。下面我們可以為三種音量狀態指定不同的圖片。

bitmapbutton.h

#include <wx/wx.h>
#include <wx/slider.h>

class BitmapButton : public wxFrame
{
public:
    BitmapButton(const wxString & title);

    wxSlider * slider;
    wxBitmapButton * button;
    int pos;

    void OnScroll(wxScrollEvent & event);

    enum{ID_SLIDER};
};

bitmapbutton.cpp

#include "bitmapbutton.h"

BitmapButton::BitmapButton(const wxString & title)
            : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(250, 130))
{
    wxImage::AddHandler(new wxPNGHandler);

    wxPanel * panel = new wxPanel(this);

    slider = new wxSlider(panel, ID_SLIDER, 0, 0, 100, wxPoint(10, 30), wxSize(140, -1));

    button = new wxBitmapButton(panel, wxID_ANY, wxBitmap(_T("muted.png"), wxBITMAP_TYPE_PNG), wxPoint(180, 20));

    Connect(ID_SLIDER, wxEVT_COMMAND_SLIDER_UPDATED,
            wxScrollEventHandler(BitmapButton::OnScroll));

    Centre();
}

void BitmapButton::OnScroll(wxScrollEvent & event)
{
    pos = slider->GetValue();

    if(pos == 0)
    {
        button->SetBitmapLabel(wxBitmap(_T("muted.png"), wxBITMAP_TYPE_PNG));
    }
    else if(pos > 0 && pos <= 30)
    {
        button->SetBitmapLabel(wxBitmap(_T("low.png"), wxBITMAP_TYPE_PNG));
    }
    else if(pos > 30 && pos < 80)
    {
        button->SetBitmapLabel(wxBitmap(_T("medium.png"), wxBITMAP_TYPE_PNG));
    }
    else
    {
        button->SetBitmapLabel(wxBitmap(_T("high.png"), wxBITMAP_TYPE_PNG));
    }
}

main.h

#include <wx/wx.h>

class MyApp : public wxApp
{
public:
    virtual bool OnInit();
};

main.cpp

#include "main.h"
#include "bitmapbutton.h"

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{
    BitmapButton * bb = new BitmapButton(_T("BitmapButton"));
    bb->Show(true);

    return true;
}

 

在我們的例子中,我們創建了一個滑塊和一個位圖按鈕,我們通過拖動滑塊改變按鈕的圖標來模仿了一個音量控制器。

wxImage::AddHandler(new wxPNGHandler);

我們將要用到PNG圖片,所以我們初始化了PNG圖像處理模塊。

button = new wxBitmapButton(panel, wxID_ANY, wxBitmap(_T("muted.png"), wxBITMAP_TYPE_PNG), wxPoint(180, 20));

我們創建了一個位圖按鈕,我們指定了位圖的類型wxBITMAP_TYPE_PNG

pos = slider->GetValue();

我們獲取了滑塊的數據,使用這個數據來設置按鈕上的不同圖標,我們有四種音量:靜音、最低、中等、最大。我們使用SetBitmapLabel()方法來改變按鈕上的圖片。

 

wxToggleButton

wxToggleButton是一個有兩種狀態的按鈕:按下或未按下,你可以通過點擊這個按鈕在這兩種狀態間切換。在有些情況下這種功能非常有用。

togglebutton.h

#include <wx/wx.h>
#include <wx/tglbtn.h>

class ToggleButton : public wxFrame
{
public:
    ToggleButton(const wxString & title);

    void OnToggleRed(wxCommandEvent & event);
    void OnToggleGreen(wxCommandEvent & evnet);
    void OnToggleBlue(wxCommandEvent & event);

protected:
    wxToggleButton * m_tgbutton1;
    wxToggleButton * m_tgbutton2;
    wxToggleButton * m_tgbutton3;

    wxPanel * m_panel;
    wxColour * colour;

    enum{ID_TGBUTTON1,
         ID_TGBUTTON2,
         ID_TGBUTTON3};
};

togglebutton.cpp

#include "togglebutton.h"

ToggleButton::ToggleButton(const wxString & title)
            : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(280, 180))
{
    wxPanel * panel = new wxPanel(this, wxID_ANY);

    colour = new wxColour(0, 0, 0);

    m_tgbutton1 = new wxToggleButton(panel, ID_TGBUTTON1, _T("Red"), wxPoint(20, 20));
    m_tgbutton2 = new wxToggleButton(panel, ID_TGBUTTON2, _T("Green"), wxPoint(20, 70));
    m_tgbutton3 = new wxToggleButton(panel, ID_TGBUTTON3, _T("Blue"), wxPoint(20, 120));

    Connect(ID_TGBUTTON1, wxEVT_COMMAND_TOGGLEBUTTON_CLICKED,
            wxCommandEventHandler(ToggleButton::OnToggleRed));
    Connect(ID_TGBUTTON2, wxEVT_COMMAND_TOGGLEBUTTON_CLICKED,
            wxCommandEventHandler(ToggleButton::OnToggleGreen));
    Connect(ID_TGBUTTON3, wxEVT_COMMAND_TOGGLEBUTTON_CLICKED,
            wxCommandEventHandler(ToggleButton::OnToggleBlue));

    m_panel = new wxPanel(panel, wxID_ANY, wxPoint(150, 20), wxSize(110, 110), wxSUNKEN_BORDER);

    m_panel->SetBackgroundColour(colour->GetAsString());

    Centre();
}

void ToggleButton::OnToggleRed(wxCommandEvent & WXUNUSED(event))
{
    unsigned char green = colour->Green();
    unsigned char blue = colour->Blue();
    if(colour->Red())
    {
        colour->Set(0, green, blue);
    }
    else
    {
        colour->Set(255, green, blue);
    }
    m_panel->SetBackgroundColour(wxColour(255, 0, 0));

    Refresh();
}

void ToggleButton::OnToggleGreen(wxCommandEvent & WXUNUSED(event))
{
    unsigned char red = colour->Red();
    unsigned char blue = colour->Blue();

    if(colour->Green())
    {
        colour->Set(red, 0, blue);
    }
    else
    {
        colour->Set(red, 255, blue);
    }
    m_panel->SetBackgroundColour(colour->GetAsString());

    Refresh();
}

void ToggleButton::OnToggleBlue(wxCommandEvent & WXUNUSED(event))
{
    unsigned char red = colour->Red();
    unsigned char green = colour->Green();

    if(colour->Blue())
    {
        colour->Set(red, green, 0);
    }
    else
    {
        colour->Set(red, green, 255);
    }
    m_panel->SetBackgroundColour(colour->GetAsString());

    Refresh();
}

main.h

#include <wx/wx.h>

class MyApp : public wxApp
{
public:
    virtual bool OnInit();
};

main.cpp

#include "main.h"
#include "togglebutton.h"

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{
    ToggleButton * button = new ToggleButton(_T("ToggleButton"));
    button->Show(true);

    return true;
}

 

在我們的例子中,我們顯示了三個開關按鈕和一個panel,我們把panel的 背景色設置為黑色,通過開關按鈕來顯示紅色綠色和藍色,背景色會根據不同開關按鈕的狀態發生改變。

colour = new wxColour(0, 0, 0);

這是一個顏色值的初始化,RGB=#000000表示黑色,理論上來說黑色不是一種顏色orz

m_tgbutton1 = new wxToggleButton(panel, ID_TGBUTTON1, _T("Red"), wxPoint(20, 20));

這里我們創建了一個開關按鈕。

Connect(ID_TGBUTTON1, wxEVT_COMMAND_TOGGLEBUTTON_CLICKED,

wxCommandEventHandler(ToggleButton::OnToggleRed));

如果我們點擊了一個開關按鈕,一個wxEVT_COMMAND_TOGGLEBUTTON_CLICKED事件產生,我們把處理函數和這個事件連接起來。注意,我們也可以不把這個事件同開關按鈕的處理函數連接,而是連接到wxFrame組件(這個開關按鈕的父親組件),因為事件指令會傳遞到父控件,在我們的例子中就是,toggle button→panel→frame。如果我們想把這個事件連接到按鈕我們應該派生出自己的按鈕類,這意味着更多的代碼。

if(colour->Red())

{colour->Set(0, green, blue);

}

else

{colour->Set(255, green, blue);

}

在事件處理函數中我們指定了不同的wxColour參數。

m_panel->SetForegroundColour(colour->GetAsString());

我們設置了panel的背景色

最后不要忘了刷新背景,原教程中由於沒有刷新背景,害我找了1小時的錯。。。坑爹啊,不知道原作者是怎么運行出來的,難道Linux會自己刷新?。。

Refresh();

刷新背景

 

wxStaticLine

這個組件在窗口內顯示一條簡單的線段,它可是水平的也可以是垂直的。

staticline.h

#include <wx/wx.h>

class Staticline : public wxDialog
{
public:
    Staticline(const wxString & title);
};

staticline.cpp

#include "staticline.h"
#include <wx/stattext.h>
#include <wx/statline.h>

Staticline::Staticline(const wxString & title)
          : wxDialog(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(360, 350))
{
    wxFont font(10, wxDEFAULT, wxNORMAL, wxBOLD);
    wxStaticText * heading = new wxStaticText(this, wxID_ANY, _T("The Central Europe"), wxPoint(30, 15));
    heading->SetFont(font);

    wxStaticLine * sl1 = new wxStaticLine(this, wxID_ANY, wxPoint(25, 50), wxSize(300,1));

    wxStaticText * st1 = new wxStaticText(this, wxID_ANY, _T("Slovakia"), wxPoint(25, 80));
    wxStaticText * st2 = new wxStaticText(this, wxID_ANY, _T("Hungary"), wxPoint(25, 100));
    wxStaticText * st3 = new wxStaticText(this, wxID_ANY, _T("Poland"), wxPoint(25, 120));
    wxStaticText * st4 = new wxStaticText(this, wxID_ANY, _T("Czech Republic"), wxPoint(25, 140));
    wxStaticText * st5 = new wxStaticText(this, wxID_ANY, _T("Germany"), wxPoint(25, 160));
    wxStaticText * st6 = new wxStaticText(this, wxID_ANY, _T("Slovenia"), wxPoint(25, 180));
    wxStaticText * st7 = new wxStaticText(this, wxID_ANY, _T("Austria"), wxPoint(25, 200));
    wxStaticText * st8 = new wxStaticText(this, wxID_ANY, _T("Switzerland"), wxPoint(25, 220));

    wxStaticText * st9  = new wxStaticText(this, wxID_ANY, _T("5 379 000"), wxPoint(220, 80), wxSize(90, -1), wxALIGN_RIGHT);
    wxStaticText * st10 = new wxStaticText(this, wxID_ANY, _T("10 084 000"), wxPoint(220, 100), wxSize(90, -1), wxALIGN_RIGHT);
    wxStaticText * st11 = new wxStaticText(this, wxID_ANY, _T("38 635 000"), wxPoint(220, 120), wxSize(90, -1), wxALIGN_RIGHT);
    wxStaticText * st12 = new wxStaticText(this, wxID_ANY, _T("10 240 000"), wxPoint(220, 140), wxSize(90, -1), wxALIGN_RIGHT);
    wxStaticText * st13 = new wxStaticText(this, wxID_ANY, _T("82 443 000"), wxPoint(220, 160), wxSize(90, -1), wxALIGN_RIGHT);
    wxStaticText * st14 = new wxStaticText(this, wxID_ANY, _T("2 001 000"),  wxPoint(220, 180), wxSize(90, -1), wxALIGN_RIGHT);
    wxStaticText * st15 = new wxStaticText(this, wxID_ANY, _T("8 032 000"),  wxPoint(220, 200), wxSize(90, -1), wxALIGN_RIGHT);
    wxStaticText * st16 = new wxStaticText(this, wxID_ANY, _T("7 288 000"),  wxPoint(220, 220), wxSize(90, -1), wxALIGN_RIGHT);

    wxStaticLine * sl2 = new wxStaticLine(this, wxID_ANY, wxPoint(25, 260), wxSize(300, 1));

    wxStaticText * sum = new wxStaticText(this, wxID_ANY, _T("164 102 000"), wxPoint(220, 280));
    wxFont sum_font = sum->GetFont();
    sum_font.SetWeight(wxBOLD);
    sum->SetFont(sum_font);

    Centre();
}

main.h

#include <wx/wx.h>

class MyApp : public wxApp
{
public:
    virtual bool OnInit();
};

main.cpp

#include "main.h"
#include "staticline.h"

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{
    Staticline * sl = new Staticline(_T("The Central Europe"));
    sl->ShowModal();
    sl->Destroy();

    return true;
}

 

在這個例子中,我們顯示了歐洲的國家和它們有的人口,使用wxStaticLine使得界面看上去更友好。

wxStaticLine * sl1 = new wxStaticLine(this, wxID_ANY, wxPoint(25, 50), wxSize(300,1));

這里我們創建了一個水平的分隔線,寬度為300像素,高度為1像素。

 

wxStaticText

一個wxStaticText組件可以顯示一行或多行只讀的文本。

statictext.h

#include <wx/wx.h>

class StaticText : public wxFrame
{
public:
    StaticText(const wxString & title);
};

statictext.cpp

#include "statictext.h"

StaticText::StaticText(const wxString & title)
          : wxFrame(NULL, wxID_ANY, title)
{
    wxPanel *panel = new wxPanel(this, wxID_ANY);
    wxString  text = wxT("'Cause sometimes you feel tired,\n\
    feel weak, and when you feel weak,\
    you feel like you wanna just give up.\n\
    But you gotta search within you,\
    you gotta find that inner strength\n\
    and just pull that shit out of you\
    and get that motivation to not give up\n\
    and not be a quitter,\
    no matter how bad you wanna just fall flat on your face and collapse.");


    wxStaticText * st = new wxStaticText(panel, wxID_ANY, text, wxPoint(10, 10), wxDefaultSize, wxALIGN_CENTRE);

    SetSize(600, 130);
    Centre();
}

main.h

#include <wx/wx.h>

class MyApp : public wxApp
{
public:
    virtual bool OnInit();
};

main.cpp

#include "main.h"
#include "statictext.h"

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{
    StaticText * st = new StaticText(_T("StaticText"));
    st->Show(true);

    return true;
}

 

在我們的例子中,我們顯示了巴拉巴拉。。。

wxStaticText * st = new wxStaticText(panel, wxID_ANY, text, wxPoint(10, 10), wxDefaultSize, wxALIGN_CENTRE);

這里我們創建了一個wxStaticText組件,靜態文本內容被放置在中央。

 

wxSlider

wxSlider是一個有一個簡單控件的組件,這個控件可以被來回拖動。有些時候使用一個滑塊比提供一個數字旋鈕(wxSpinCtrl)更加自然。

slider.h

#include <wx/wx.h>
#include <wx/slider.h>

class MyPanel : public wxPanel
{
public:
    MyPanel(wxFrame * parent);

    void OnPaint(wxPaintEvent & event);
    void OnScroll(wxScrollEvent & event);

    wxSlider * slider;
    int fill;

    enum{ID_SLIDER};
};

class Slider : public wxFrame
{
public:
    Slider(const wxString & title);

    MyPanel * panel;
};

slider.cpp

#include "slider.h"

Slider::Slider(const wxString & title)
      : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(270, 200))
{
    panel = new MyPanel(this);

    Centre();
}

MyPanel::MyPanel(wxFrame * parent)
       : wxPanel(parent, wxID_ANY)
{
    fill = 0;
    slider = new wxSlider(this, ID_SLIDER, 0, 0, 140, wxPoint(50, 30), wxSize(-1, 140), wxSL_VERTICAL);

    Connect(ID_SLIDER, wxEVT_COMMAND_SLIDER_UPDATED, wxScrollEventHandler(MyPanel::OnScroll));

    Connect(wxEVT_PAINT, wxPaintEventHandler(MyPanel::OnPaint));
}

void MyPanel::OnScroll(wxScrollEvent & event)
{
    fill = slider->GetValue();
    Refresh();
}

void MyPanel::OnPaint(wxPaintEvent & event)
{
    wxPaintDC dc(this);

    wxPen pen(wxColour(212, 212, 212));
    dc.SetPen(pen);

    dc.DrawRectangle(wxRect(140, 30, 80, 140));

    wxBrush brush1(wxColour(197, 108, 0));
    dc.SetBrush(brush1);

    dc.DrawRectangle(wxRect(140, 30, 80, fill));
}

main.h

#include <wx/wx.h>

class MyApp : public wxApp
{
public:
    virtual bool OnInit();
};

main.cpp

#include "main.h"
#include "slider.h"

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{
    Slider * slider = new Slider(_T("Slider"));
    slider->Show(true);

    return true;
}

 

在我們的例子中,我們顯示了一個滑塊控件。我們通過拖動這個滑塊來改變panel的背景色,在這種類型的程序中,使用一個滑塊比一個數字旋鈕方便的多。

slider = new wxSlider(this, ID_SLIDER, 0, 0, 140, wxPoint(50, 30), wxSize(-1, 140), wxSL_VERTICAL);

我們創建了一個垂直滑塊,初值為0,最小值是0,最大值為140,我們沒有顯示標尺。

Connect(ID_SLIDER, wxEVT_COMMAND_SLIDER_UPDATED, wxScrollEventHandler(MyPanel::OnScroll));

這里我們把wxEVT_COMMAND_SLIDER_UPDATED事件同OnScroll()方法連接起來。

Connect(wxEVT_PAINT, wxPaintEventHandler(MyPanel::OnPaint));

我們也要畫一些圖案,所以我們把OnPaint()方法和wxEVT_PAINT事件連接起來。

fill = slider->GetValue();

Refresh();

在OnScroll()方法中,我們獲得了滑塊當前的值,我們調用Refresh()方法產生了一個wxEVT_PAINT方法。

dc.DrawRectangle(wxRect(140, 30, 80, 140));

wxBrush brush1(wxColour(197, 108, 0));

dc.SetBrush(brush1);

dc.DrawRectangle(wxRect(140, 30, 80, fill));

在OnPaint()方法里面,我們畫了兩個矩形,第一個是灰色邊框的白色矩形,第二個是一個褐色的矩形。矩形的高度由滑塊的當前值fill控制。

 

在這一章的wxWidgets教程中,我們簡要的概括了幾個組件。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM