在这一章中,我们会继续介绍一些组件的知识,我们会提到wxListBox,wxNotebool和wxScrolledWindow。
wxListBox
一个wxListBox组件被用来显示一些元素,它是一个有一系列字符串的矩形。我们可以使用它来显示一个MP3文件的列表,一些书名,或者是一个大工程的模块名。一个wxListBox可以以两种不同的状态被创建。一个单一选择的状态或者一个多重选择的状态。单一状态是默认的状态,在wxListBox里面有两个事件类型,第一个是wxEVT_COMMAND_LISTBOX_SELECTED,当我们选择wxListBox里面的一个元素时这个事件产生;第二个是wxEVT_COMMAND_LISTBOX_DOUBLE_CLICKED,当我们双击wxListBox里面的一个元素时这个事件产生。在wxListBox内部的元素在GTK的平台上有限制,大概不能超过2000个左右的元素。元素的ID从0开始计算,滚动条会在需要的时候自动生成。
listbox.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #include <wx/wx.h> #include <wx/listbox.h> class MyPanel : public wxPanel { public: MyPanel(wxPanel * parent); void OnNew(wxCommandEvent & event); void OnRename(wxCommandEvent & event); void OnClear(wxCommandEvent & event); void OnDelete(wxCommandEvent & event); wxListBox * m_lb; wxButton * m_newb; wxButton * m_renameb; wxButton * m_clearb; wxButton * m_deleteb; }; class Listbox : public wxFrame { public: Listbox(const wxString & title); void OnDbClick(wxCommandEvent & event); wxListBox * listbox; MyPanel * btnPanel; }; enum{ID_RENAME, ID_LISTBOX};
|
listbox.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| #include "listbox.h" #include <wx/textdlg.h> Listbox::Listbox(const wxString & title) : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(270, 200)) { wxPanel * panel = new wxPanel(this, wxID_ANY); wxBoxSizer * hbox = new wxBoxSizer(wxHORIZONTAL); listbox = new wxListBox(panel, ID_LISTBOX, wxDefaultPosition, wxDefaultSize); btnPanel = new MyPanel(panel); hbox->Add(listbox, 3, wxEXPAND | wxALL, 20); hbox->Add(btnPanel, 2, wxEXPAND | wxRIGHT, 10); Connect(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, wxCommandEventHandler(Listbox::OnDbClick)); panel->SetSizer(hbox); Centre(); } MyPanel::MyPanel(wxPanel * parent) : wxPanel(parent, wxID_ANY) { wxBoxSizer * vbox = new wxBoxSizer(wxVERTICAL); Listbox * lb = (Listbox*)parent->GetParent(); m_lb = lb->listbox; m_newb = new wxButton(this, wxID_NEW, _T("New")); m_renameb = new wxButton(this, ID_RENAME, _T("Rename")); m_deleteb = new wxButton(this, wxID_DELETE, _T("Delete")); m_clearb = new wxButton(this, wxID_CLEAR, _T("Clear")); Connect(wxID_NEW, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MyPanel::OnNew) ); Connect(ID_RENAME, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MyPanel::OnRename) ); Connect(wxID_CLEAR, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MyPanel::OnClear) ); Connect(wxID_DELETE, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MyPanel::OnDelete) ); vbox->Add(-1, 20); vbox->Add(m_newb); vbox->Add(m_renameb, 0, wxTOP, 5); vbox->Add(m_deleteb, 0, wxTOP, 5); vbox->Add(m_clearb, 0, wxTOP, 5); SetSizer(vbox); } void MyPanel::OnNew(wxCommandEvent & event) { wxString str = wxGetTextFromUser(_T("Add new item")); if(str.Len() > 0) { m_lb->Append(str); } } void MyPanel::OnClear(wxCommandEvent & event) { m_lb->Clear(); } void MyPanel::OnRename(wxCommandEvent & event) { wxString text; wxString renamed; int sel = m_lb->GetSelection(); if(sel != -1) { text = m_lb->GetString(sel); renamed = wxGetTextFromUser(_T("Rename item"), _T("Rename dialog"), text); } if(!renamed.IsEmpty()) { m_lb->Delete(sel); m_lb->Insert(renamed, sel); } } void MyPanel::OnDelete(wxCommandEvent & event) { int sel = m_lb->GetSelection(); if(sel != -1) { m_lb->Delete(sel); } } void Listbox::OnDbClick(wxCommandEvent & event) { wxString text; wxString renamed; int sel = listbox->GetSelection(); if(sel != -1) { text = listbox->GetString(sel); renamed = wxGetTextFromUser(_T("Rename item"), _T("Rename dialog"), text); } if(!renamed.IsEmpty()) { listbox->Delete(sel); listbox->Insert(renamed, sel); } }
|
listbox = new wxListBox(panel, ID_LISTBOX, wxDEFAULT_POSITION, wxDEFAULT_SIZE);
这个是listbox组件的构造器.
在我们的例子中,我们有一列四个按钮,这些按钮用来在listbox内添加、修改、删除、清空元素。
wxString str = wxGetTextFromUser(_T(“Add new item”));
if(str.Len() > 0)
{
m_lb->Append(str);
}
我们使用上面的代码显示一个wxGetTextFromUser对话框接收用户输入,然后调用Append()函数添加到listbox内。
m_lb->Clear();
清空listbox只需要简单的调用一个Clear()方法。
int sel = m_lb->GetSelection();
if(sel != -1)
{
m_lb->Delete(sel);
}
我们调用GetSelection()方法计算出当前选中的是第几项,然后我们调用Delete()方法删除元素。
修改一个元素需要以下几个步骤:
wxString text;
wxString renamed;
我们定义了两个字符串对象。
int sel = listbox->GetSelection();
if(sel != -1)
{
text = listbox->GetString(sel);
Renamed = wxGetTextFromUser(_T(“Rename item”), _T(“Rename dialog”), text);
}
我们获取了当前选中的的字符串,并保存起来,然后请求用户的输入。
if(!renamed.IsEmpty())
{
m_lb->Delete(sel);
m_lb->Insert(renamed, sel);
}
我们检查了renamed字符串是否为空,避免了插入空字符串,然后我们删除了旧的元素,插入新的元素。
wxNotebook
wxNotebook可以在一个窗体上通过标签列举多个窗口。可以通过下面四个标识符指定标签的位置:
- wxNB_LEFT
- wxNB_RIGHT
- wxNB_TOP
- wxNB_BOTTOM
默认的是wxNB_TOP
notebook.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include <wx/wx.h> #include <wx/notebook.h> #include <wx/grid.h> class Notebook : public wxFrame { public: Notebook(const wxString & title); void OnQuit(wxCommandEvent & event); }; class MyGrid : public wxGrid { public: MyGrid(wxNotebook * parent); };
|
notebook.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include "notebook.h" Notebook::Notebook(const wxString & title) : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(400, 350)) { wxNotebook * nb = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_BOTTOM); wxMenuBar * menubar = new wxMenuBar(); wxMenu * file = new wxMenu(); file->Append(wxID_EXIT, _T("Quit"), _T("")); menubar->Append(file, _T("&File")); SetMenuBar(menubar); Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(Notebook::OnQuit)); MyGrid * grid1 = new MyGrid(nb); MyGrid * grid2 = new MyGrid(nb); MyGrid * grid3 = new MyGrid(nb); nb->AddPage(grid1, _T("Sheet1")); nb->AddPage(grid2, _T("Sheet2")); nb->AddPage(grid3, _T("Sheet3")); CreateStatusBar(); Centre(); } void Notebook::OnQuit(wxCommandEvent & event) { Close(true); } MyGrid::MyGrid(wxNotebook * parent) : wxGrid(parent, wxID_ANY) { CreateGrid(30, 30); SetRowLabelSize(50); SetColLabelSize(25); SetRowLabelAlignment(wxALIGN_RIGHT, wxALIGN_CENTER); SetLabelFont(wxFont(9, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD)); for(int i = 0; i < 30; i++) { this->SetRowSize(i, 25); } }
|
在这个例子中,我们创建了一个包含三个表格控件的notebook组件,notebook的标签被放置在窗体底部。
wxNotebook * nb = new wxNotebook(this, wxID_ANY, wxDEFAULTPOSITION, wxDEFAULTSIZE, wxNB_BOTTOM);
这里我们创建了一个notebook组件。
nb->AddPage(grid1, _T(“Sheet1”));
nb->AddPage(grid2, _T(“Sheet2”));
nb->AddPage(grid3, _T(“Sheet3”));
我们添加了三个表格控件到notebook组件中。
这是容器组件中的其中一个。当我们有一个比屏幕还要大的区域需要显示时,这个组件很有用。在我们的例子中,我们示范了它的用法,我们在窗口中放置了一个巨大的图片。当窗口比我们的图片小的时候,滚动条会自动显示。
scrolledwindow.h
1 2 3 4 5 6 7
| #include <wx/wx.h> class ScrolledWindow : public wxFrame { public: ScrolledWindow(const wxString & title); };
|
scrolledwindow.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include "scrolledwindow.h" ScrolledWindow::ScrolledWindow(const wxString & title) : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(300, 200)) { wxImage::AddHandler(new wxJPEGHandler); wxScrolledWindow * sw = new wxScrolledWindow(this); wxBitmap bmp(_T("test.jpg"), wxBITMAP_TYPE_JPEG); wxStaticBitmap * sb = new wxStaticBitmap(sw, -1, bmp); int width = bmp.GetWidth(); int height = bmp.GetHeight(); sw->SetScrollbars(10, 10, width / 10, height / 10); sw->Scroll(50, 10); Centre(); }
|
在我们的例子中,我们显示了一张海贼王的图片。
wxImage::AddHandler(new wxJPEGHandler);
我们必须初始化wxJPEGHandler,才能处理jpg图像。
wxScrolledWindow * sw = new wxScrolledWindow(this);
wxBitmap bmp(_T(“test.jpg”), wxBITMAP_TYPE_JPEG);
wxStaticBitmap * sb = new wxStaticBitmap(sw, -1, bmp);
我们创建了一个滚动窗口,并放置了一张静态图。
sw->SetScrollbars(10, 10, width / 10, height / 10);
我们设置了滚动条。
sw->Scroll(50, 10);
滚动到初始位置。
在这一章中,我们继续介绍了wxWidgets库中的组件。