Створення крос-платформених GUI-додатків з використанням wxWidgets, Різне, Програмування, статті

Набір інструментальних засобів wxWidgets містить потужні крос-платформні засоби розробки графічного інтерфейсу користувача (GUI). Не тільки “рідний” C + +, але й інші мови програмування пропонують засоби для використання даного інструментального набору. Дізнайтеся, як використовувати wxWidgets для створення елегантних і дуже корисних GUI-додатків на улюбленому вами мовою програмування.


Чому потрібно використовувати wxWidgets? Тому що ви хочете швидко і просто написати GUI-додаток, який працює на різних платформах. Ви також хочете використовувати бажаний вами мову програмування і бажаєте, щоб ваш GUI виглядав так само добре, як GUI на наступному малюнку:


Рисунок 1. Поштовий клієнт Chandler
Рисунок 1. Поштовий клієнт Chandler

На малюнку 1 показана програма Chandler, призначена для керування електронною поштою та календарем і розробляється організацією Open Source Application Foundation. Вона пишеться з використанням інструментального набору wxWidgets. Хоча оригінальна версія wxWidgets реалізована на C + +, творці Chandler використовують Python з набором інструментальних засобів wxPython, що виступає як “оболонки”, що дозволяє Python-коду взаємодіяти з бібліотекою C + +. wxWidgets використовує, по можливості, “рідні” об’єкти; ці об’єкти доповнюються (там, де необхідно) потужними користувацькими віджетами. Ви можете написати wxWidgets-програму, яка буде працювати на широкому різноманітті платформ, а також можете використовувати різні мови програмування для цього.


Початок роботи з wxWidgets


У даній статті я припускаю, що ви вже відвідали домашню сторінку wxWidgets і завантажили потрібний пакет для вашої платформи. Я також припускаю, що ви виконали на вашому комп’ютері команди або настройки по інтеграції бібліотеки wxWidgets з обраним вами компілятором або інтегрованої середовищем розробки (integrated development environment – IDE). Після всього цього ви можете приступити до кодування.


Основними компонентами wxWidgets-програми є два головних об’єкта: об’єкт-додаток і об’єкт-фрейм. Ви, звичайно ж, можете мати більше одного фрейма. Крім того, у вашому коді вам знадобиться розмістити кілька wxWidgets-макросів. Розглянемо, як скомпонувати ці частини.


Посилання на бібліотеку wxWidgets


Щоб посилатися на бібліотеку wxWidgets, ви повинні включити її в код. Помістіть наступний рядок у верхній частині ваших заголовків (header) файлів:






#include “wx/wx.h”

Заголовний файл wx / wx.h містить всі wxWidgets-визначення, які вам можуть знадобитися. Якщо ви дуже турбуєтеся про продуктивність, можете замінити цей файл операторами include з конкретними заголовками, які збираєтеся використовувати.


Визначення класу додатка


Далі ви повинні визначити клас додатки. У більшості простих випадків цей клас робить не так вже й багато, але у вас він повинен бути. wxWidgets-додаток успадковується з класу wxApp, І мінімальне визначення виглядає так:






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

Функція OnInit() викликається при запуску вашого застосування – практично, це ваш метод main().


Після визначення класу програми помістіть абикуди в ваш код наступний макрос:






IMPLEMENT_APP(DemoApp)

Ви повинні замінити DemoApp на ім’я вашого класу додатки. Цей макрос створює реальний метод main(), Який wxWidgets використовує. Він також створює екземпляр об’єкту програми і починає процес ініціалізації.


Визначення класу фрейма


Тепер визначте клас фрейма, який буде представляти головне вікно вашої програми. Батьківським класом wxWidgets є wxFrame. У лістингу 1 наведений короткий приклад.


Лістинг 1. Приклад класу wxFrame





class DemoFrame : public wxFrame {
public:
DemoFrame(const wxString& title);
void OnButtonPress(wxCommandEvent& event);
private:
DECLARE_EVENT_TABLE()
};

Розглянемо імена, які вам можуть бути не знайомі. wxString – Це спеціалізований wxWidgets-клас, який є оболонкою над string і використовується для операцій з рядками в інструментальному наборі wxWidgets. wxWidgets не використовує класи Standard Template Library (STL), для того щоб не обмежувати використання wxWidgets платформами, на яких доступна STL (якщо захочете, можете вказати ключ командного рядка під час компіляції для використання STL). Аналогічно, wxCommandEvent – Один з батьківських класів для подій, зокрема, керуючих (command) подій, які представляють собою високорівневі події, зазвичай пов’язані з дій користувача, наприклад, натискання кнопки або вибір зі списку. Нарешті, макрос DECLARE_EVENT_TABLE потрібен будь wxWidgets-об’єкту, що бажає реагувати на події. Цей макрос в даній статті реалізує невеликий демонстраційний фрейм.


Визначення таблиці подій


Для реального реагування на події ви повинні визначити таблицю подій всередині ваших файлів. Це ще один макрос, і він (у нашому випадку) виглядає так, як показано в лістингу 2.


Лістинг 2. Макрос таблиці подій





BEGIN_EVENT_TABLE(DemoFrame, wxFrame)
EVT_BUTTON(wxID_CLOSE, DemoFrame::OnButtonPress)
END_EVENT_TABLE()

Макрос BEGIN_EVENT_TABLE() приймає два аргументи: клас, для якого призначена таблиця подій, і прямий предок цього класу. Макрос END_EVENT_TABLE, Як і очікується, позначає кінець таблиці подій. Між цими макросами ви можете вказати будь-яке число макросів для конкретних подій. У прикладі цієї статті використовується тільки один.


Інструментальний набір wxWidgets має декілька різних макросів подій, кожен з яких відповідає різним типам подій. В даному випадку EVT_BUTTON відповідає натисненню на кнопку. Першим параметром макросу є ідентифікатор, який вказує конкретну кнопку, яка буде оброблятися. Ідентифікатор wxID_CLOSE є одним з декількох зумовлених ідентифікаторів, пов’язаних зі звичайними функціональними можливостями програми. Зумовлений ідентифікатор тут використовується виключно для зручності, хоча в деяких випадках використовуються спеціалізовані ідентифікатори, які активізують спеціальну обробку системою wxWidgets. Другим параметром макросу є повністю кваліфіковане ім’я методу, який повинен бути викликаний при активізації події. Всі події в wxWidgets управляються з використанням макросів подій, аналогічних описаним.


Визначення ваших методів


Тепер настав час почати визначати деякі методи. Я показую три простих методу, починаючи з методу OnInit(), Наведеного в лістингу 3.


Лістинг 3. Метод OnInit ()





bool DemoApp::OnInit() {
DemoFrame *frame = new DemoFrame(“DeveloperWorks Demo”);
frame->Show(true);
return true;
}

Перші два рядки методу роблять те, що ви і очікували б при старті GUI-програми – вони створюють і показують головне вікно. Однак третій рядок, насправді, є найважливішою для застосування. Повернення значення true вказує механізму wxWidgets на те, що ініціалізація пройшла успішно, і програма може продовжувати свою роботу. Повернення значення false, Навпаки, зупинив би додаток і викликав би вихід з нього.


Метод OnInit () посилається на конструктор DemoFrame. У цьому конструкторі ви додаєте кнопку в ваш фрейм, як показано в лістингу 4.


Лістинг 4. Додавання кнопки в ваш фрейм





DemoFrame::DemoFrame(const wxString& title)
: wxFrame(NULL, wxID_ANY, title) {
wxSizer *sizer = new wxBoxSizer(wxVERTICAL);
this->SetSizer(sizer);
wxButton *button = new wxButton(this, wxID_CLOSE, “Click Me”);
sizer->Add(50, 50);
sizer->Add(button, 0, wxALL, 50);
}

Перед додаванням кнопки у фрейм ви створюєте калібратор (sizer). Калібратор є wxWidgets-еквівалентом менеджерів схем мови програмування Java: калібратори дозволяють вам використовувати зумовлені правила для розміщення об’єктів у вашому вікні замість необхідності вказівки розміру і позиції кожного віджета окремо. В даному випадку ви використовуєте wxBoxSizer, Який розміщує віджети на прямій лінії (цей калібратор може бути вертикальним або горизонтальним). Після створення калібратора ви приєднуєте його до фрейму за допомогою методу SetSizer(). Потім ви створюєте кнопку. Параметри для конструктора кнопки такі:



Вам не потрібно явно додавати кнопку у фрейм; досить вказівки фрейма як батьківського контейнера. Однак, ви повинні явно додати кнопку в калібратор, для того щоб алгоритм схеми розміщення калібратора знав про неї. Це робиться в останньому рядку методу, але не перед додаванням порожній області розміром 50 x 50 пікселів на початку рядка. При додаванні кнопки ви вказуєте також калібратором оточити кнопку кордоном товщиною в 50 пікселів. Це робиться шляхом використання прапора wxALL і останнього аргументу – числа 50.


Визначення обробника подій


Нарешті, ви визначаєте простий обробник подій, показаний в лістингу 5.


Лістинг 5. Простий обробник подій





void DemoFrame::OnButtonPress(wxCommandEvent& event) {
Close(true);
}

Більш простого додатка ви зробити не зможете. Відкомпілюйте його і побачите симпатичне вікно з однією кнопкою, показане на малюнку 2. Натисніть кнопку, вікно закриється. В wxWidgets закриття останнього батьківського фрейма викликає вихід з програми, тому натискання на кнопку викликає завершення роботи програми.


Рисунок 2. Демонстраційне вікно
Рисунок 2. Демонстраційне вікно

Даний приклад, природно, тільки поверхнево зачіпає можливості wxWidgets.


wxPython


Хоча wxWidgets є потужним набором інструментальних засобів, не кожен захоче мати справу з деструкторами C + +, управлінням пам’яттю і всім іншим. На щастя, група талановитих програмістів створила інтерфейсну оболонку для бібліотеки wxWidgets, яку можна використовувати з інших мов програмування. Тому, навіть якщо C + + не є вашим улюбленим засобом програмування, ви все одно можете скористатися перевагами бібліотеки wxWidgets.


Самою зрілою і повністю розробленої интерфейсной оболонкою wxWidgets є wxPython, за допомогою якої ви можете створювати wxWidgets-програми, використовуючи мову програмування Python. Завантажувані пакети існують для платформ Microsoft Windows, Mac і Linux, а також є досить велика і активна спільнота користувачів. Як все це виглядає? Python-програма, показана в лістингу 6, створює точно таке ж порожнє вікно, яке ви створили раніше на C + +.


Лістинг 6. Python-додаток, що відображає пусте вікно





#!/usr/bin/env python
import wx
class DemoApp(wx.App):
def OnInit(self):
frame = DemoFrame(parent=None, id=-1, title=”DeveloperWorks”)
frame.Show()
return True
class DemoFrame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title)
sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(sizer)
button = wx.Button(self, wx.ID_CLOSE, “Click Me”)
sizer.Add((50, 50))
sizer.Add(button, 0, wx.ALL, 50)
self.Bind(wx.EVT_BUTTON, self.OnButtonClick)
def OnButtonClick(self, event):
self.Close(True)
if __name__ == “__main__”:
app = DemoApp()
app.MainLoop()

Як ви можете бачити, в цій програмі існує практично однозначна відповідність між API-викликами на C + + і wxPython-викликами. В обох випадках ви створюєте об’єкт докладання і об’єкт фрейму. Ви також починаєте з методу OnInit() і визначаєте схожі конструктори і обробники об’єктів.


Найбільшою відмінністю в даному конкретному прикладі є зв’язування подій з обробниками. Там, де C + +-версія виконує це зв’язування за допомогою макросів таблиці подій, Python-версія використовує метод Bind(), Який приймає в якості аргументів Python-об’єкт, що представляє тип події та метод, що викликається при настанні події. Така структура використовує здатність Python розглядати методи як змінні і передавати їх в якості аргументів точно так само, як типи string або integer.


Переваги wxPython перед C + + wxWidgets починають проявлятися у великих або більш складних програмах. Якщо не відволікатися на дебати про відносні переваги C + + і Python як мов програмування, існують деякі відмінні функциональнее можливості, властиві wxPython-версії, які можуть бути привабливі для вас. Механізм обробки подій з використанням методів Bind() більш легко вписується в wxPython-версію, ніж в wxWidgets. В Python-версії легше динамічно оновити ваші обробники під час виконання. Деякі складні або складові віджети, такі як деревовидні списки або залежна кнопка з зображенням, є стандартними в wxPython, але їх немає в C + +-версії. Також wxPython містить пакет засобів розробки Py, який робить тривіальної завдання додавання інтерактивної налагодження в вашу wxPython-програму.


wxEverythingElse


Python – це не єдина мова програмування, що має засоби доступу до бібліотеки wxWidgets. Хоча wxPython є зрілим пакетом, варто оцінити й інші пакети, якщо ви віддаєте перевагу працювати з конкретним мовою програмування. Давайте коротко розглянемо деякі інші пакети з wxWorld. Зверніть увагу, будь ласка, на те, що оцінка стабільності і функціональності цих проектів залежить від доступних матеріалів. Багато з цих проектів є результатом праці одного або двох програмістів. Якщо вас цікавить проект для конкретної мови, перевіряйте його самостійно.


wxPerl


Остання основна версія wxPerl вийшла в червні 2006. Надаються щоденні копії, але доступна документація застаріла на декілька років. Активність списку розсилки становить 2-3 повідомлення в день. Бінарні завантажувальні файли доступні для Win32, Linux і Mac OS X. Крім основного набору інструментальних засобів доступно також кілька додаткових наборів, включаючи OpenGL-оболонку і пакувальник для створення додатків Mac OS X.


Головним завданням в wxPerl є перетворення wxWidgets API в унікальну Perl-різновид об’єктно-орієнтованого програмування (OOP). Показаний у лістингу 7 фрагмент створює фрейм, аналогічний розглянутому вище прикладу.


Лістинг 7. Приклад вікна в wxPerl





package MyFrame;
use base “Wx::Frame”;
use Wx::Event qw(EVT_BUTTON);
sub new {
my $class = shift;
my $self = $class->SUPER::new(undef, -1, “Trying wxPerl”,
[-1, -1], [250, 200]);
my $sizer = Wx::BoxSizer->new(wxVERTICAL);
my $button = Wx::Button->new($self, -1, “Click me!”, [-1, -1],
[-1, -1]);
EVT_BUTTON($self, $button, &OnButtonClick);
$sizer->Add($button);
$self->SetSizer($sizer);
return $self;
}
sub OnButtonClick {
my($self, $event) = @_;
$self->SetTitle(“You Did It”);
}

Цей код є, по суті, порядковим перекладом вихідного коду з C + + і Python, який ви вже бачили. В даному випадку бібліотека wxWidgets поставляється у вигляді Perl-пакета, а також використовується виклик функції EVT_BUTTON, Який виглядає аналогічно визначенню макросу в C + +-версії.


wxRuby


Проект wxRuby знаходиться в дещо не простому стані. Існує сира програма, в якій зв’язування з wxWidgets API здійснюється вручну. Остання версія цієї програми була випущена в листопаді 2004, і з цього часу тривала (з перервами) розробка версії, яка використовує більш потужну програму Simplified Wrapper and Interface Generator (SWIG) для генерування зв’язків між Ruby і wxWidgets. Нова версія була недавно описана в списку розсилки як майже готова: “Через пару днів …, чи, можливо, протягом кількох місяців”.


Одним цікавим моментом щодо wxRuby є те, що на відміну від більшості інших wxWidgets-оболонок у розробників є можливість підганяти імена API-викликів wxWidgets, для більшого відповідаючи угоди про найменуваннях в Ruby (наприклад, lower_case_with_underscores замість wxWidgets UpperCaseWithCamelCase). Тобто, в той час як весь наведений вище код прикладів використовував функцію SetSizer(), WxRuby викликає set_sizer(). За винятком цього частина wxRuby-програми, що працює з wxWidgets API, буде практично аналогічна наведеним вище


Мир wxWidgets


Інші порти wxWidgets знаходяться на різних стадіях завершеності або незавершеності. Нижче представлений короткий екскурс в область wxWidgets:



Резюме


Мир wxWidgets може багато чого запропонувати програмістам всіх мастей. Базовий набір програм є гнучким і може задовольнити більшість ваших GUI-потреб. Різні пакети для зв’язування дозволяють wxWidgets знаходитися в межах досяжності для більшості програмістів. Використання інструментального набору wxWidgets з віддається перевага мовою програмування допоможе вам створити відмінно виглядають інтерфейси для ваших власних додатків.


Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*