среда, июля 01, 2009

Первая программа на wxWidgets

От нечего делать решил написать маленький тьюториал. В своё время меня по-настоящему достало отсутствие нормальных обучалок по wxWidgets.
Прежде всего, обговорю два момента. Во-первых, я надеюсь,что мой читатель знает,что такое библиотека wxWidgets, что он умеет программировать на C++, что он уже установил себе всё необходимое и настроил компилятор (самый простой способ на Windows - это поставить IDE wxDev-Cpp, на Linux все способы одинаково простые) и что он горит желанием начать.
Второе - это то,что я хочу сейчас сделать. Я хочу создать минимальное рабочее GUI-приложение на wxWidgets, не обращая пристального внимания на оптимизации и трюки. Из чего состоит минимальное приложение? Дайте подумать...кусочек текста на сером фоне подойдёт.
Сперва даю код,после этого - объясняю,что он делает, договорились?

1 #include <wx/wx.h>
2
3 class MainApp: public wxApp{
4 public:
5 virtual bool OnInit();
6 };
7
8 class MainFrame: public wxFrame{
9 public:
10 MainFrame( const wxString &title, const wxPoint &pos, const wxSize &size );
12 };
13
14 DECLARE_APP(MainApp)
15 IMPLEMENT_APP(MainApp)
16 bool MainApp::OnInit(){
17 MainFrame *MainWin = new MainFrame(_("Заголовок окна"), wxDefaultPosition, wxSize(580, 200));
18 MainWin->Show(true);
19 SetTopWindow(MainWin);
20 return true;
21 }
22
23 MainFrame::MainFrame(const wxString& title, const wxPoint& pos, const wxSize& size):wxFrame((wxFrame *) NULL, -1, title, pos, size) {
24 new wxStaticText (this, wxID_ANY, _T("Я написал что-то на wxWidgets!!"), wxPoint(10,100), wxDefaultSize,0,wxStaticTextNameStr);
25 }


За этими 25 строчками кроется глубинный смысл. Пока что скомпилируйте, а я расскажу,что да как. Напоминаю,что на Linux это делается командой:


g++ `wx-config --cxxflags` <ЗДЕСЬ_ИМЯ_ФАЙЛА> `wx-config --libs` -o <ИМЯ_БИНАРНИКА>


Начнём,пожалуй. Строка 1 подключает собственно wxWidgets. Для случая прекомпиляции предусмотрен иной подход, но что я говорил насчет оптимизаций?
Итак, на строке 3 мы создаём класс MainApp. Это будет основной класс нашей программы,о чём напоминают строчки 14 и 15.В строках 8-12 создаётся фрейм программы - собственно окошечко, в котором будет виден текст. Позднее туда ещё добавится пара контролов.

Если вы заметили,то программа не содержит функции main(). Вместо неё первой выполняется функция OnInit(),это строки 16-21. В них всё довольно топорно: пичкаем фрейм нужными параметрами (заголовок, позиция на экране и размер), выводим на экран, и даём команду сделать его основным окном программы.

В строках 23-25 описывается содержимое фрейма. Собственно, что и будет выведено после выполнения строки 18. У нас это безымянный текстовый блок. немного о параметрах конструктора:

new wxStaticText (this, wxID_ANY, _T("Я написал что-то на wxWidgets!!"), wxPoint(10,100), wxDefaultSize,0,wxStaticTextNameStr);

this - это указатель на окно,в котором выводится текстовый блок. У нас, собственно,и нет выбора.
Значение wxID_ANY нужно объяснять долго. wxWidgets использует систему ID - то есть,каждый объект на фрейме имеет собственный целочисленный номер. Это понадобится чуть позже, когда придётся обрабатывать события. Пока что обработка событий в наши планы не входит, поэтому и ID мы задаём произвольным образом.
wxPoint(10,100) - это положение тестового блока на фрейме. Объект класса wxPoint задаёт его левый верхний угол - здесь только две координаты, которые считаются от левого верхнего угла.Вместо этого можно написать wxDefaultPosition - размещение по умолчанию, но ведь лёгкими путями не достигнуть просветления.
Здесь хотелось бы сделать замечание. При ручной расстановке я заметил,что в разных осях разные шрифты и размеры блоков. Так, в одной операционке мне не хватает ширины на фрейме,в другой - высоты. Разница в шрифтах, разница в размере границ полей..всё это даёт сильные перекосы, поэтому старайтесь придерживаться всё-таки стандартных компоновщиков,это сильно сэкономит нервы и время.
wxDefaultSize - размер блока. Рекомендую не вычислять вручную, библиотека это превосходно сделает за вас.
0 - отвечает за стиль текста. Если интересно - смотреть здесь. Но в большинстве случаев вам это смотреть не понадобится.
wxStaticTextNameStr - имя окна. Играть с этим не требуется,но если есть желание - почитайте маны и попробуйте.

Итак, вроде всё. У нас получилось одинокое окошко с текстовым блоком.Попробуем чуть-чуть усложнить задачу. За что я не люблю остальные руководства - они думают, что статусбар и меню - это обязательные элементы интерфейса. Чушь собачья! Интерфейс должен быть максимально простым и требовать не больше одного клика мышки.Что требует всего лишь одного нажатия? Кнопка.

Так, на сегодня пока всё. В следующий раз попробуем сделать ещё одну бессмысленную программу, в которой значение текстового поля будет меняться с щелчком кнопки. При желании, кнопку можно будет сделать красной :-)

3 комментария:

  1. Спасибо!
    Интересно, а какой размер у такой программы?

    ОтветитьУдалить
  2. Смотря как и где будете компилировать - я говорю об операционной системе, компиляторе и его настройках. Можно линковать wxWidgets статически - тогда программа будет самодостаточной, но будет весить больше на мегабайт (как минимум). Можно включить динамическую линковку, это сильно уменьшит размер программы - но сделает её зависимой от библиотеки (то есть, либо опять же вы поставляете DLL или .so с программой, либо заставляете искать пользователя).
    "Hello,World!" на Windows под Mingw со статической линковкой у меня, по-моему, занимало один или полтора мегабайта,не больше. Зато код полностью кроссплатформен.

    ОтветитьУдалить
  3. О,и я забыл добавить - усложнение программы мало влияет на рост размера бинарника, потому что библиотека уже не изменяется в размере :-)
    С этим можно как-то бороться, используя Ассемблер (импортом нужных функций напрямую из библиотеки), и следя за используемыми функциями (wxWidgets - модульная библиотека, и вы можете отключать неиспользуемые её части).Но факт есть факт: чтобы пользоваться библиотекой, понадобится её иметь.Плюс в том,что это не GTK+, которая весит под 30 Мб.
    Ну, и хорошо уменьшает размер программы и убыстряет её, конечно, переключение компилятора в Release Mode вместо стандартного Debug. Удивительно, но об этом многие забывают.

    ОтветитьУдалить

Постоянные читатели

Архив