Створення крос-платформених GUI-застосувань з використанням wxWidgets

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


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


Малюнок 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. Демонстраційне вікно

Даний приклад, природно, тільки поверхнево зачіпає можливості 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>

*

*