Sl-Alex домашняя лаборатория

Руководство по WxWidgets: 8. Виджеты часть 2

Просмотров: 2462Комментарии: 0
Статьи
Руководство по WxWidgets: 8. Виджеты часть 2

В этой главе мы продолжим знакомство с различными виджетами. А в конце главы, как обычно, вас ждут ссылки на остальные материалы курса.

wxListBox (Окно списка)

Окно списка (лист бокс) используется для отображения и работы со списком объектов. Как следует из названия - это прямоугольник внутри которого находится список строк. Мы можем использовать его для отображения списка mp3 файлов, названий книг, модулей большого программного проекта, имен друзей. У этого виджета есть два режима работы: режим одиночного выбора и режим множественного выбора. По-умолчанию задаётся режим одиночного выбора. С лист боксом связано два важных события. Первое: wxEVT_COMMAND_LISTBOX_SELECTED. Это событие генерируется когда мы выбираем сроку в лист боксе. Второе: wxEVT_COMMAND_LISTBOX_DOUBLE_CLICKED. Оно генерируется, когда мы дважды щёлкаем на объекте в лист боксе. Количество элементов внутри лист бокса ограничено платформой GTK. В соответствии с документацией это число не должно превышать 2000 элементов. Элементы нумеруются с нуля. Полосы прокрутки появляются автоматически, когда в этом возникает необходимость.

Listbox.h
#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 OnDblClick(wxCommandEvent& event);
	wxListBox *listbox;
	MyPanel *btnPanel;
};
const int ID_RENAME = 1;
const int ID_LISTBOX = 5;
Listbox.cpp
#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, -1);
	wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL);
	listbox = new wxListBox(panel, ID_LISTBOX, 
		wxPoint(-1, -1), wxSize(-1, -1)); 
	hbox->Add(listbox, 3, wxEXPAND | wxALL, 20);
	btnPanel = new MyPanel(panel);
	hbox->Add(btnPanel, 2, wxEXPAND | wxRIGHT, 10);
	Connect(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, 
		wxCommandEventHandler(Listbox::OnDblClick));
	panel->SetSizer(hbox);
	Center();
}
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, wxT("New"));
	m_renameb = new wxButton(this, ID_RENAME, wxT("Rename"));
	m_deleteb = new wxButton(this, wxID_DELETE, wxT("Delete"));
	m_clearb = new wxButton(this, wxID_CLEAR, wxT("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(wxT("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(wxT("Rename item"), 
			wxT("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::OnDblClick(wxCommandEvent& event) 
{
	wxString text;
	wxString renamed;
	int sel = listbox->GetSelection();
	if (sel != -1) {
		text = listbox->GetString(sel);
		renamed = wxGetTextFromUser(wxT("Rename item"), 
			wxT("Rename dialog"), text);
	} 
	if (!renamed.IsEmpty()) {
		listbox->Delete(sel);
		listbox->Insert(renamed, sel);
	}
}
main.h
#include <wx/wx.h>
class MyApp : public wxApp
{
	public:
		virtual bool OnInit();
};
main.cpp
#include "main.h"
#include "Listbox.h"
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
	Listbox *listbox = new Listbox(wxT("Listbox"));
	listbox->Show(true);
	return true;
}
listbox = new wxListBox(panel, ID_LISTBOX, 
	wxPoint(-1, -1), wxSize(-1, -1));

Это конструктор виджета окна списка.

В нашем примере мы использовали лист бокс и четыре кнопки, которые служат для добавления, переименования, удаления и очистки всех элементов списка.

wxString str = wxGetTextFromUser(wxT("Add new item"));
if (str.Len() > 0)
	m_lb->Append(str);

Чтобы добавить новую строку в лист бокс, мы отображаем диалог wxGetTextFromUser, а потом вызываем метод Append(), который добавляет полученную с помощью диалога строку в список.

m_lb->Clear();

Для очистки всех элементов списка нужно просто вызвать метод Clear().

int sel = m_lb->GetSelection();
if (sel != -1) {
	m_lb->Delete(sel);
}

Для удаления элемента мы вычисляем выбранный элемент, а потом вызываем метод Delete().

Переименование элементов осуществляется в несколько шагов.

wxString text;
wxString renamed;

Мы определили две локальные переменные.

int sel = listbox->GetSelection();
if (sel != -1) {
	text = listbox->GetString(sel);
	renamed = wxGetTextFromUser(wxT("Rename item"), 
		wxT("Rename dialog"), text);
}

Мы получаем выбранную строку и сохраняем её в переменной renamed.

if (!renamed.IsEmpty()) {
	m_lb->Delete(sel);
	m_lb->Insert(renamed, sel);
}

Мы проверяем не является ли переменная renamed пустой. Это для предотвращения добавления пустых строк. После этого мы удаляем старый элемент и добавляем новый.

Рисунок 8.1: Listbox

Рисунок 8.1: Listbox

wxNotebook (Записная книжка)

Записная книжка - это виджет объединяющий множество окон с соответствующими ярлыками. Вы можете позиционировать записную книжку с помощью следующих флагов:

  • wxNB_LEFT (Слева)
  • wxNB_RIGHT (Справа)
  • wxNB_TOP (Сверху)
  • wxNB_BOTTOM (Снизу)

Позицией по-умолчанию является сверху.

Notebook.h
#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
#include "Notebook.h"
Notebook::Notebook(const wxString& title)
	: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(400, 350))
{
	wxNotebook *nb = new wxNotebook(this, -1, wxPoint(-1, -1), 
		wxSize(-1, -1), wxNB_BOTTOM);
	wxMenuBar *menubar = new wxMenuBar;
	wxMenu *file = new wxMenu;
	file->Append(wxID_EXIT, wxT("Quit"), wxT(""));
	menubar->Append(file, wxT("&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, wxT("Sheet1"));
	nb->AddPage(grid2, wxT("Sheet2"));
	nb->AddPage(grid3, wxT("Sheet3"));
	CreateStatusBar();
	Center();
}
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_CENTRE);
	SetLabelFont(wxFont(9, wxFONTFAMILY_DEFAULT, 
		wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD));
	for (int i = 0; i < 30 ; i++) {
		this->SetRowSize(i, 25);
	}
}
main.h
#include <wx/wx.h>
class MyApp : public wxApp
{
	public:
		virtual bool OnInit();
};
main.cpp
#include "main.h"
#include "Notebook.h"
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
	Notebook *notebook = new Notebook(wxT("Notebook"));
	notebook->Show(true);
	return true;
}

В этом примере мы создали виджет записной книжки с тремя таблицами и поместили его снизу.

wxNotebook *nb = new wxNotebook(this, -1, wxPoint(-1, -1), 
	wxSize(-1, -1), wxNB_BOTTOM);

Здесь мы создали записную книжку.

nb->AddPage(grid1, wxT("Sheet1"));
nb->AddPage(grid2, wxT("Sheet2"));
nb->AddPage(grid3, wxT("Sheet3"));

Мы добавили три объекта таблицы в записную книжку

Рисунок 8.2: wxNotebook

Рисунок 8.2: wxNotebook

wxScrolledWindow (Прокручивающееся окно)

Это один из виджетов контейнеров. Он может быть полезен, когда у нас отображаемая область больше чем окно. В нашем примере мы демонстрируем как раз такой случай. Мы поместили в наше окно изображение большого размера. Когда окно меньше, чем наше изображение автоматически появляются полосы прокрутки.

scrolledwindow.h
#include <wx/wx.h>
class ScrWindow : public wxFrame
{
public:
	ScrWindow(const wxString& title);
};
scrolledwindow.cpp
#include "scrolledwindow.h"
ScrWindow::ScrWindow(const wxString& title)
	: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(300, 200))
{
	wxImage::AddHandler(new wxJPEGHandler);
	wxScrolledWindow *sw = new wxScrolledWindow(this);
  
	wxBitmap bmp(wxT("castle.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);
	Center();
}
main.h
#include <wx/wx.h>
class MyApp : public wxApp
{
	public:
		virtual bool OnInit();
};
main.cpp
#include "main.h"
#include "scrolledwindow.h"
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
	ScrWindow *sw = new ScrWindow(wxT("ScrolledWindow"));
	sw->Show(true);
	return true;
}

В нашем примере мы выводим изображение замка "Спишский Град" (Словакия).

wxImage::AddHandler(new wxJPEGHandler);

Для обработки jpeg изображений мы должны инициировать соответствующий обработчик wxJPEGHandler.

wxScrolledWindow *sw = new wxScrolledWindow(this);
wxBitmap bmp(wxT("castle.jpg"), wxBITMAP_TYPE_JPEG);
wxStaticBitmap *sb = new wxStaticBitmap(sw, -1, bmp);

Мы создали прокручивающееся окно и поместили в него объект wxStaticBitmap.

sw->SetScrollbars(10, 10, width/10, height/10);

Установили полосы прокрутки.

sw->Scroll(50,10);

Немного прокрутили окно.

Рисунок 8.3: Окно с прокруткой

Рисунок 8.3: Окно с прокруткой

Остальные материалы курса:

Вступление

1. Вспомогательные классы

2. Первые программы

3. Меню и панели инструментов

4. Управление компоновкой

5. События

6. Диалоги

7. Виджеты часть 1

8. Виджеты часть 2

9. Перетаскивание

10. Контексты устройств

11. Самодельные виджеты

12. Тетрис в wxWidgets

Примечание

Оригинал руководства расположен здесь. Автор оригинала - Jan Bodnar.

Перевод (без разметки и картинок) был выполнен пользователем ber113 с сайта translated.by. К сожалению, сайт сейчас не работает.

Данный документ представляет собой компиляцию указанных документов с сохранением оригинальной разметки и иллюстраций.