Уроки wxSmith: Hello world
Урок 1. "Hello, World!"
[править]Английский оригинал wiki текста доступен по ссылке. Автор первоначального текста: BYO на codeblocks.org [1]
Вступление
[править]На этом первом уроке wxSmith мы отобразим слова «Hello, World!» на экране. С тех пор как в 1978 году появился язык программирования Си, написание такой программы было традиционно первым шагом в изучении почти каждого языка программирования.
Прежде чем мы начнем, необходимо загрузить и скомпилировать библиотеку wxWidgets. Существует два способа установки библиотек wxWidgets:
- Можно загрузить исходный код wxWidgets и скомпилировать его самостоятельно. Как это делается, описано на странице: Настройка wxWidgets в Code::Blocks.
- либо можно загрузить wxPack с wxpack.sourceforge.net и установить его. WxPack содержит предварительно скомпилированную библиотеку wxWidgets, поэтому можно сэкономить достаточное количество времени пойдя этим путём.
Примечания:
- Лучше всё таки немножко потрудиться и скомпилировать wxWidgets самостоятельно, чем надеяться, что кто-то когда-то правильно и именно для этого компилятора всё подготовил. Сложность самостоятельной компиляции невелика, но нужно правильно и внимательно выставить опции, которые потребуются при настройке проекта.
- Пользователи Ubuntu Linux могут установить wxWidgets из репозиториев Ubuntu. Обязательно установите также build-essential, чтобы получить компилятор C.
Предположим, что у вас есть wxWidgets, готовый и работающий с Code::Blocks. Вероятно, вы должны создать каталог с именем, наподобие CBProjects, для сохранения вашей работы над этими уроками. Каждый урок будет отдельным проектом ("project") и будет занимать файл в этом каталоге.
Создаем новый проект wxWidgets
[править]После загрузки и установки Code::Blocks дважды щелкните значок на рабочем столе, чтобы запустить его. Вот окно открытия Code::Blocks:
Нажмите «Создать новый проект»,
а затем найдите и дважды щелкните значок проекта wxWidgets Project, на который указывает курсор на скриншоте ниже.
Следующий экран - экран «Добро пожаловать».
Если вам вовсе не нравится приветствие программы, установите флажок, который устраняет его при запуске в будущем.
Следующий экран выглядит следующим образом:
Выберите wxWidgets 2.8x и нажмите кнопку "Next >" в нижней части экрана.
Это приведет к открытию окна, где нужно указать название и папку проекта, в которых вы хотите сохранить проект. Затем заполняются другие поля. Например, в качестве названия проекта выбран «HelloWorld», а затем (автоматически) настроены остальные поля, что выглядит следующим образом:
Затем нажмите кнопку “Next >” внизу. Следующий экран, показанный ниже, позволяет пометить вашу работу своей личными данными. Заполните то, что пожелаете.
Это вызывает окно для выбора построителя GUI, который вы хотите использовать: wxSmith или FormBuilder. Выбираем, конечно же, wxSmith.
Нажмите кнопку "Next" в нижней части.
На следующем экране нужно указать расположение библиотеки WxWidgets с которой будет компоноваться проект:
Оставьте настройку по умолчанию $(#wx). Это ссылка на глобальную переменную wx, которая задает путь к wxWidgets в настройках Code::Blocks. Также если это расположение никогда не указывалось ранее может быть открыта форма настройки глобальных переменных:
Нужно указать "корневой" каталог библиолитеки wxWidgets в поле "base". Обратите внимение, чтобы в поле "current variable" при этом была выбрана переменная "wx".
Следующий экран мастера настойки задаёт, какой компилятор C++ мы хотим использовать и хотим ли мы отладочную сборку (с дополнительным кодом для отладки) или меньшую по размерам конечную сборку (для конечного пользователя). Выбираем компилятор GNU CPP и параметры обеих сборок: расположить в отдельных вложенных папках.
На последнем экране такого рода уточняется, хотим ли мы использовать стандартные настройки по умолчанию или использовать дополнительные опции.
Примем вариант по умолчанию. Но, внизу, мы выбираем опцию “Create and use precompiled headers" (создание и использование предварительно скомпилированных заголовков), которая ускоряет следующие за первой компиляции. Обратите также внимание, что опции библиотеки wxWidgets должны быть проставлены в стогом соответствии с параметрами, использованными при сборке (компиляции) библиотек, иначе проект не будет собираться.
В форме выбора каталога для сохранения проекта мы выбрали реальный каталог, но, такой выбор может привести к проблемам, если потребуется скомпилировать проект на других компьютерах. Другой вариант заключается в использовании глобальной переменной системы. Чтобы открыть ниже диалоговое окно или модифицировать или изменить эту глобальную переменную, нужно нажать на пункт главного меню Code::Blocks Settings | Global variables. Это открывает редактор глобальных переменных.
Если им воспользоваться, расположение библиотеки wxWidgets будет считываться из переменной, которую вы зададите. Это означает, что местоположение каталога wxWidgets задано не жестко внутри вашего проекта, а хранится внутри глобальной конфигурации Code::Blocks. Когда проект открыт на другом компьютере, он будет использовать конфигурацию этого (другого) компьютера. Самый простой вариант для использования этой глобальной переменной является оставить $(#wx), что означает использовать глобальную переменную с именем wx. Это имя зарезервировано для wxWidgets и его следует выбирать в большинстве случаев.
Когда глобальная переменная используется в первый раз, будет запрошен каталог wxWidgets. Единственное, что вам в этом случае нужно сделать - ввести правильное расположение в поле base. Такая необходимость возникает только при первом использовании, так как в дальнейшем Code::Blocks будет автоматически использовать указанный параметр для других проектов, которые вы создаете.
Обзор интерактивной среды разработки (IDE)
[править]В конце этой предварительной последовательности форм мы вышли в главное окно среды IDE Code::Blocks. Оно должно выглядеть примерно так:
В середине правой стороны окна, под словом «HelloWorldframe.wxs», находится панель с двумя квадратными значками (иконками) на левой стороне ; тот, что слева открывает редактор строки меню, а тот, что справа открывает редактор строки статуса. Вернемся к редактору строки меню в следующем уроке. Ниже этой панели находится окно редактора, которое выглядит, как поле точек. В нем можно видеть создаваемые формы графического интерфейса пользователя, и написанный нами код C++. В левом нижнем углу окна находится окно Properties/Events (Свойства/События), которое позволяет задать свойства компонента, с которым мы работаем или выбрать события, такие как «OnClick», которым мы задаём обработку. Чтобы показать свойства, нажмите на значок (иконку) слева; чтобы показать события, нажмите на значок справа помеченный {} - вызов кода C++.
Выше окна Properties/Events находится окно Management (управление) с тремя вкладками: Projects (проекты), Symbols (символы) и Resources (ресурсы). Если не видны все три вкладки, перетащите правую границу окна вправо, чтобы отобразить все три.
Примечания:
- В более поздних версиях Code::Blocks вкладок стало больше - добавлены ещё две: Files и FSymbols.
- Последовательность вкладок можно менять, просто перетащив нужную вкладку вправо или влево, как удобнее. Например, чтобы сузить ширину окна Management можно сделать первой Projects, второй Resources, а остальные (не используемые в этом уроке) скрыть сдвигая правую границу окна влево.
- «Resource» в терминологии wxSmith обычно означает «форма» или «окно».
Выше окна Management находится панель с несколькими небольшими, но очень нужными значками ():
- Build the program - собрать программу, или
- Run - запустить её, или
- Build and run - собрать и запустить её, или
- Rebuild - пересобрать её, или
- Abort - прервать её.
Если над ними удерживать курсор, всплывающие подсказки подскажут, что есть что.
Теперь посмотрим обратно в окно редактора. Во-первых, обратите внимание, что окно можно настроить для использования разных цветов, шрифтов и размеров шрифтов. Нажмите "Settings ..." в главном меню Code::Blocks, и затем "Editor". В содержимом экрана можно так или иначе разобраться самостоятельно.
Теперь вернемся в окно редактора. В его верхней части вы видите пять черных квадратиков, которые называются ручки перетаскивания. Они установлены для покрытия пространства больше, чем можно увидеть, но прокрутка вниз показывает все поле.
Как опытный программист вы знаете, где-то там должен быть некоторый код, но вы не видите его. Чтобы раскрыть его, щелкните дважды левой кнопкой мыши в области точек. Вуаля, вот и код C++, а над ним появилась вкладка HelloWorldMain.cpp. Нажав на HelloWorldframe.wxs можно снова вернуться в представление формы, которое по-прежнему выглядит в виде поля с точками. (Опять же, важно иметь Code::Blocks 10.04 или более поздней версии). Ах да, мы еще совсем не видели кода. В частности вы напрасно будете искать наиважнейшую процедуру OnInit(), которая запускает эту программу. Тем не менее, найти её можно нажав Search | Find in Files (Поиск | Найти в файлах), где область поиска OnInit будет “Project files” (Файлы проекта). Поиск находит его, конечно же, в HelloWorldApp.cpp и открывает этот модуль в окне редактора.
Нам не требуется OnInit прямо сейчас, но мы должны внести изменения в HelloWorldMain.cpp. Щелкните на нем в строке над редактором, а его код отображается в редакторе.
Иногда программе нужно много что сделать, когда пользователь щелкает значок Закрыть в заголовке окна (например, чтобы выполнить операции сохранения перед закрытием программы), поэтому wxSmith создает каркас для написания кода для этих действий, но он создает никакого кода. Следовательно, если мы запустили нашу программу в первоначальном созданном wxSmith виде, у нас не будет возможности закрыть её, просто нажав значок. Чтобы исправить эту проблему, найти место в коде с этими строками:
void PlainFrame::OnClose(wxCloseEvent& event) { }
Добавьте вызов Close() функции, так чтобы место выглядит следующим образом:
void PlainFrame::OnClose(wxCloseEvent & event) { Destroy(); }
Также можно использовать команду event.Skip(TRUE) вместо Destroy().
Не забудьте сделать это изменение сразу же всякий раз, когда вы начинаете новый проект.
В новых релизах указанный ниже код вставляется автоматически:
void PlainFrame::OnQuit(wxCommandEvent& event) { Close(); }
Теперь можно собрать и запустить эту супер-простенькую программу. Чтобы сделать это, вы можете выполнить любое из трех эквивалентных действий:
- В верхней строке меню, нажмите кнопку Build | Build and run.
- Найдите и нажмите на значок, который выглядит как треугольник перед шестерней. Наведение курсора мыши над ним будет показывать подсказку “Build and run”.
- Нажмите клавишу F9.
Если все пойдет хорошо, вы увидите окно с меню из двух пунктов: File and Help. Сначала попробуйте пункт меню "Help". Затем вы можете использовать “File | Quit” или значок выход в заголовке, чтобы выйти из программы.
Итак, у нас есть программа, которая запускается и завершает работу, но она еще не отображает «Hello, World!». Двигаемся дальше.
Hello, World!
[править]Теперь мы переходим к классической первой программе, а именно получению слова «Hello, World!» на экране. Текст может быть добавлен непосредственно в окно, как конструкторах GUI для одной операционной системы; но мы должны научиться использовать разместители (sizers) для кросс-платформенного программирования. Что такое разместители?
Если вы работали с Java или Qt, вы можете вспомнить что-то, что называется Layout managers. Их реализация в wxWidgets немного отличается, но делает почти то же самое.
При добавлении компонентов в окна необходимо каким-то образом указать их положение и размер. wxWidgets пытается автоматизировать этот процесс, и он использует для этого разместители. Они автоматически задают положение и размер компонентов окна и они также могут задавать размер окна, так чтобы все умещалось внутри.
Разместители имеют одно большое преимущество над прямым размещением компонентов. При написании кросс-платформенных приложений, нельзя быть уверенным в том, что шрифты, кнопки и т.д. имеют одинаковый размер в различных операционных системах. Эта проблема может произойти даже на той же платформе при использовании разных тем окон. Когда вы используете разместители, вам не нужно беспокоиться об этих проблемах. Все управление размерами и размещением выполняется автоматически. Более того, разместители даже могут перемещать и изменять размер оконных компонентов, когда основное окно изменяет размер.
Исходя из этого, давайте начнем. Если посмотреть на редактор wxSmith, можно заметить, что область окна окружена восемью черными квадратиками или ручками перетаскивания.
Эти ручки перетаскивания окружают текущий выбранный элемент. В нашем случае это цельное окно. Добавление новых компонентов в окно выполняется довольно просто: нужно щелкнуть мышью одну из кнопок в палитре внизу редактора, а затем щелкнуть где-нибудь на ресурсе. Как видите,
если удерживать курсор мыши над компонентом в палитре, он покажет свое имя. Эта функция может помочь найти компоненты, пока вы не познакомитесь с их значками.
Давайте добавим новый компонент wxPanel в наше окно; это четвертая иконка слева на вкладке Standard. Обратите внимание, что когда вы нажмете элемент wxPanel, а затем переместите курсор над редактором, часть редактора изменит цвет. Это происходит намеренно и используется, чтобы показать, где в окне будет добавлен новый элемент.
После того, как wxPanel будет установлен на форму, можно заметить, что цвет фона окна изменился на светло-серый. Теперь наше окно будет больше похоже на другие окна. Обратите внимание, что теперь выбранный элемент изменился на добавленную панель, но поскольку его размер равен кадру, трудно определить, что действительно выбрано. Чтобы убедиться, что выбран именно wxPanel, щелкните где-нибудь в светло-серой области нашего окна (Замечание пользователей Linux: wxFrame и wxPanel обычно имеют один и тот же фон, поэтому может показаться, что ничего не изменилось. Однако вы можете убедиться, что wxPanel есть, взглянув в браузер ресурсов).
Если требуется точно выбрать выделение или выбрать элементы, которые перекрываются, вы можете использовать для этого браузер ресурсов. Чтобы продемонстрировать это, перейдите на вкладку ресурсов, расположенную в том же месте, где находится браузер проекта:
Вкладка ресурсов состоит из двух частей. Первое - это дерево ресурсов, которое показывает структуру ваших ресурсов, а второе - браузер свойств, который является общим для конструторов GUI. В дереве ресурсов можно найти выбранный элемент. В нашем случае это класс wxPanel, который мы добавили ранее. Выбранный элемент также показывает имя этого элемента: Panel1. Это имя является переменной, которая может использоваться для доступа к этому компоненту в вашем коде.
Мы добавили новый компонент, выбрав место для него. Это поведение wxSmith по умолчанию. Однако есть еще один способ добавления элементов. В этом режиме новый элемент добавляется сразу после нажатия кнопки палитры. Позиция нового элемента относится к текущему выбору - точно так же, как курсор в текстовых редакторах. По существу мы можем добавлять новые элементы в три разные позиции относительно выбора:
- перед выбранным виджетом
- после выбранного виджета
- в выбранный виджет.
Этот режим вставки можно изменить, щелкнув одну из четырех кнопок размещения в правой части редактора:
Самый верхний - режим, который мы использовали - указание мышью. Следующий означает добавить в, затем добавить до, а последний означает добавить после. Текущий режим отображается красной галочкой на кнопке.
Иногда несколько режимов выбора отключены, поскольку они недействительны для текущего выбранного элемента. Например, вы не можете добавить какой-либо компонент в компонент wxButton, поскольку wxWidgets объявляет его как тот, который не может иметь дочерние компоненты. Аналогично, когда выбран основной компонент (окно), вы не сможете ничего добавить после него или перед ним.
Упс! Я сказал, что мы будем использовать разместители, а потом совершенно забыли о них! Мы должны избавиться от этой wxPanel. Выберите панель, а затем нажмите красную кнопку X чуть ниже четырех кнопок, которые мы описывали. Она выглядит так:
Когда вы нажимаете эту кнопку, она удаляет текущий выбор, поэтому, если панель не исчезла, убедитесь, что она выбрана, и снова нажмите кнопку. Теперь мы должны были вернуться в начальное состояние.
Чтобы использовать разместители, сначала мы должны добавить разместитель в основное окно, а затем добавить wxPanel в него. Разместители доступны на вкладке Layout (макет) на палитре. Перейдите к нему и выберите wxBoxSizer:
Этот разместитель пытается позиционировать элементы в одной строке, горизонтальной или вертикальной. Горизонтальное расположение - по умолчанию, и мы будем использовать его.
После добавления разместителя изменились две вещи. Во-первых, наше окно теперь имеет красную границу. Это означает, что к нему прикреплен разместитель. Если взглянуть в браузер ресурсов, можно также увидеть, что разместитель добавлен. (Возможно, вам нужно щелкнуть по области редактора, чтобы обновить выделение в браузере ресурсов.) Второе изменение заключается в том, что размер окна сократился до небольшого квадратика. Так и должно быть, потому что разместитель отвечает за изменения размера окна, дабы оно было не больше, чем необходимо, чтобы быть видимым и приспособленным к его компонентам, а пока что оно не содержит компонентов.
Теперь давайте добавим наш wxPanel. Убедитесь, что вы добавили его в разместитель, а не в главное окно. После того, как вы так сделаете, вы увидите нечто вроде этого:
Здесь мы видим нашу панель, окруженную ручками перетаскивания. Также имеется какая-то темно-серая граница вокруг него (она невидима на Linux). Каждый компонент добавленный в разместитель может быть окружен такой границей. Это используется, когда нужно иметь интервал между компонентами. Но в нашем случае мы должны избавиться от неё, чтобы получить лучше выглядящее окно. Чтобы сделать это, нам придется изменить свойства в обозревателе свойств. Найдите размер границы (border size) и измените его с 5 до 0:
Теперь, когда наша панель настроена, наконец, можно добавить текст «Hello world». Поскольку мы также будем использовать разместители для управления элементами добавленными в wxPanel, мы должны повторить добавление разместителя wxBoxSizer в wxPanel. После того, как разместитель находится на своем месте, переключитесь обратно во вкладку Standard на палитре и добавьте элемент управления wxStaticText:
С прицелом на будущее и чтобы попрактиковаться в добавлении компонентов давайте добавим кнопку рядом с wxStaticText. Первым делом нажмите на wxButton. Если у вас режим вставки «указание мышью» ещё включен, то при наведении мыши на компонент wxStaticText, половина этого компонента будет окрашена в свет синий. Когда текст выделен в левой половине, новый элемент будет добавляться до существующего компонента; а когда выделена правая половина, новый компонент будет добавлен после существующего. Давайте добавим кнопку после текста. Теперь мы должны получить следующее:
Теперь давайте наконец установим наш текст «Hello, World!». Элемент управления wxStaticText, который мы добавили ранее, содержит текст Label. Это текст по умолчанию для всех вновь созданных классов wxStaticText. Мы изменим его с помощью обозревателя свойств аналогично тому, как меняли размер границы в классе wxPanel. Чтобы сделать это, выберите компонент wxStaticText в нашем окне, затем найдите свойство Label в обозревателе свойств и измените его значение на «Hello, World!»:
Если вы хотите две или более строк текста в элементе управления wxStaticText нажмите на кнопку «...», в правом конце строки “Label” или поставить "\n" внутри текста, как это предусмотрено в формате языка C.
Теперь можете нажать "Build and run", и программа должна запуститься и показать магические слова в элементе управления статический текст. На этом мы могли бы триумфально закончить, но кнопка, которую мы поставили на форму по прежнему не работает; щелчок на ней не будет делать ничего. Давайте дадим ей функцию.
Прежде чем двигаться дальше, нам придется иметь дело с вопросом, который у вас наверняка возникнет. Зачем, после расположения разместителя box sizer на нашем главном окне, требуется положить в него wxPanel и затем положить еще один box sizer на панели? Для чего нужна панель? Почему бы просто не положить наши две кнопки в первый box sizer и тем самым устранить панель и второй box sizer? Ответ: потому что панель дает нам управление фоном. Мы не обязаны её использовать, но часто бывает полезно иметь возможность управлять им. Фактически эти первые три шага будут использоваться в структурировании каждого окна, используемого в наших уроках. Для повторения, эти три шага:
- положить box sizer на окно
- вложить панель в первый box sizer
- положить разместитель какого нибудь типа на панель.
Отклик на щелчок кнопки
[править]Так как кнопки обычно вызывают какое то действие при нажатии, давайте сделаем нашу кнопку закрывающей окно. Первое, что мы должны сделать, заключается в том, чтобы изменить текст, отображаемый на кнопке, чтобы сообщить пользователю, что кнопка делает. Это делается, точно так же как и в случае с элементом wxStaticText. Выберите кнопку, найдите Label в обозревателе свойств и поменяйте его значение на "Close" (или что-нибудь, что вам нравится).
Далее нужно назначить этой кнопке обработчик событий. В своей основе обработчики событий — это функции, которые вызываются при возникновении некоторых «событий». В нашем случае вместо «событие» можно сказать более описательно - «нажатие на кнопку», потому что это то, что мы хотим обработать. Как и другие конструкторы GUI, wxSmith может автоматически генерировать код каркаса для таких обработчиков. Чтобы использовать эту возможность, переключитесь из браузера свойств в браузера событий, нажав на второй значок в верхней части обозревателя свойств. Этот значок изображает {} тем самым предлагая код C++.
После нажатия на этот значок, вы увидите все события, поддерживаемые текущим выбранным компонентом. Класс wxButton поддерживает только одно событие - событие EVT_BUTTON, поэтому только его и можно видеть. Когда вы нажмете на это событие и распахнете поле со списком, вы увидите доступные параметры и обработчики для этого события:
Если выбрать -- None -- функция обработчика к этому событию автоматически назначаться не будет. (Но она всегда может быть установлена вручную). Выбор -- Add new handler -- будет генерировать каркас для кода новой функции обработчика. Ниже приведены другие обработчики событий, известных wxSmith, которые могут быть назначены к этому событию. Мы видим здесь, OnQuit и OnAbout. Эти обработчики были созданы мастером. Мы могли бы использовать обработчик OnQuit, но чтобы увидеть, что происходит, напишем наш собственный обработчик. Выберите вариант Add new handler. У вас будет запрошено имя обработчика. Это имя — просто имя функции, которая будет вызываться в качестве реакции на это событие. wxSmith будет предложено имя OnButton1Click, и мы можем также использовать его.
При вводе нового имени обработчика, wxSmith будет генерировать каркас кода новой функции обработчика с таким именем. Откройте файл программы с нужным исходным кодом и поместите курсор внутри функции обработчика. (Может потребоваться прокрутка вверх или вниз, чтобы показать строку с курсором.) Эта функция является членом класса, который мы создали, поэтому она может получить доступ ко всем функции в этом классе, включая функцию Close(), которая была создана с помощью мастера. Поэтому, когда мы хотим закрыть наше окно, мы просто вызываем функцию Close(). Результат выглядит так:
Выполните сборку и запуск нашего проекта. Он должен показать наш текст «Hello, World!» и нашу кнопку "Close".
Нажмите кнопку Close, и он должен закрыться.
Это конец первого урока. Надеюсь, что вы легко справились и начали чувствовать себя комфортно с Code::Blocks и wxSmith.