Методология разработки приложений с использованием форм. Создание приложений с графическим интерфесом Создание программ с графическим интерфейсом c

Аннотация: Изучаются выджеты - визуальные элементы, из которых состоит графический интерфейс пользователя, их компоновка, политика размеров, сигнально-слотовые соединения, элементы графического интерфейса и их использование.

13.1 Виджеты (Widgets)

Виджеты (Widgets ) - это визуальные элементы, из которых состоит графический интерфейс пользователя.

Примеры виджетов:

  • Кнопка (класс QPushButton );
  • Метка (класс QLabel );
  • Поле ввода (класс QLineEdit );
  • Числовое поле-счётчик (класс QSpinBox );
  • Строка прокрутки (класс QScrollBar ).

В Qt есть около 50-ти готовых классов графических элементов доступных для использования. Родительским классом для всех виджетов является класс QWidget . От него наследуются все главные свойства визуальных элементов, которые мы тщательно рассмотрим. Исследование способов разработки программ с графическим интерфейсом начнём с примера.

Создадим пустой файл проекта. Запустим мастера проектов и выберем в разделе Projects (Проекты) пункт Other Project (Другой проект) . Далее выберем тип проекта Empty Qt Project (Пустой проект Qt) . К файлу проекта добавим содержимое:

TEMPLATE = app #Модули Qt, которые мы будем использовать QT += widgets #Добавляем модуль widgets для работы с виджетами (необходимо для Qt5). TARGET = widget#Название исполняемого файла SOURCES += \ main.cpp

Теперь создадим простую программу с окном, в котором мы будем выводить надпись. Установим размер окна и текст его заголовка, а также установим шрифт для надписи. Для этого создадим файл main.cpp со следующим содержанием:

#include #include int main (int lArgc, char * lArgv ) { //Создаём объект QApplication, который инициализирует и настраивает оконную программу, //управляет её выполнением с помощью цикла обработки событий QApplication lApplication (lArgc, lArgv); QLabel lLabel; //Создаём виджет QLabel - метка lLabel.setText (" I am widget! "); //Задаём текст для метки lLabel.setGeometry (200, 200, 300, 150); //Задаём размеры - позицию (x, y) ширину и высоту. Задаём выравнивание текста lLabel.setAlignment (Qt::AlignHCenter | Qt::AlignVCenter); //Класс QFont используют для настройки параметров шрифта. //Выбираем семейство шрифтов Arial Black и размер 12. QFont lBlackFont (" Arial Black ", 12); lLabel.setFont (lBlackFont); //Задаём шрифт для метки lLabel.show (); //Вызываем метод show() для показа метки на экране. return lApplication.exec (); //Запускаем программу на выполнение exec() выполняет //цикл обработки событий. Программа ожидает действия пользователя и выполняет их обработку. }

Как видим, элементы, из которых состоят интерфейсы в Qt , имеют собственные позицию и размер - так называемую "геометрию" - и, таким образом, занимают соответствующую прямоугольный участок на экране (см. рис. 13.1). Также каждый из элементов имеет настройки, которые определяют его поведение и вид.


Рис. 13.1.

Для создания структуры виджеты организовывают в иерархию по принципу "часть - целое". Каждый из виджетов может содержать другие виджеты. Такой визуальный элемент становится "родителем" (родительским виджетом) для элементов, которые он содержит. Отметим, что такие отношения не следует путать с наследованием в C++ - отношениями между классами в программе. Отношения между виджетами являются отношениями между объектами. Такие отношения порождают несколько последствий:

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

Виджеты, которые не имеют родителя (виджеты верхнего уровня), имеют вид отдельных окон в программе. Рассмотрим пример. Назовём новый проект ParentExample . Файл проекта будет содержать обычные для GUI -проекта настройки:

TEMPLATE = app TARGET = ParentExample QT += widgets

Для виджета, который мы будем использовать в качестве главного окна создадим новый класс. Для этого в категории Files and Classes (Файлы и классы) выберем раздел С++ и выберем С++ Class (см. рис. 13.2).

Следующим шагом будет создание нескольких элементов на окне. Для этого откроем файл parentwidget.cpp и изменим код конструктора класса. Для отображения элементов достаточно создать их в конструкторе класса и задать ParentWidget как отца для них. Код parentwidget.cpp выглядит так:

#include " parentwidget.h " #include #include #include ParentWidget::ParentWidget (QWidget * parent) : QWidget (parent) { //Создаём метку, указывая родительский виджет - this, то есть экземпляр класса ParentWidget. QLabel * lLabel=new QLabel (this); //Позиция относительно левого верхнего угла родительского виджета. lLabel ->setGeometry (50, 0, 100, 30); lLabel ->setText (" TextLabel "); //Текст на метке. //Создаём кнопку, задаём "родителя", геометрию и текст QPushButton * lPushButton = new QPushButton (this); lPushButton->setGeometry (50, 50, 100, 30); lPushButton->setText (" PushButton "); //Создаём поле ввода, задаём "родителя", геометрию и текст QLineEdit * lLineEdit = new QLineEdit (this); lLineEdit ->setGeometry (50, 100, 100, 30); lLineEdit ->setText (" LineEdit "); lLineEdit ->selectAll (); //Выделяем текст в поле ввода (просто для примера) //Наконец изменяем размер родительского виджета setGeometry (x (), y (), 300, 150); //и задаём текст заголовка окна setWindowTitle (" parent widgetExample "); }

Поскольку родительским элементом является ParentWidget , то метка (QLabel ), кнопка (QPushButton ) и текстовое поле (QLineEdit) находятся в его пределах. Позицию дочерних виджетов задают относительно левого верхнего угла отца. В этом легко убедиться изменив размеры и позицию окна нашей программы. Обратите внимание на то, как мы создавали элементы пользовательского интерфейса в динамической памяти используя оператор new . Это гарантирует, что элементы не будут удалены после завершения работы конструктора ParentWidget .

Последнее обновление: 07.10.2019

Интерфейс представляет ссылочный тип, который может определять некоторый функционал - набор методов и свойств без реализации. Затем этот функционал реализуют классы и структуры, которые применяют данные интерфейсы.

Определение интерфейса

Для определения интерфейса используется ключевое слово interface . Как правило, названия интерфейсов в C# начинаются с заглавной буквы I , например, IComparable, IEnumerable (так называемая венгерская нотация), однако это не обязательное требование, а больше стиль программирования.

Что может определять интерфейс? В целом интерфейсы могут определять следующие сущности:

  • Свойства

    Индексаторы

  • Статические поля и константы (начиная с версии C# 8.0)

Однако интерфейсы не могут определять нестатические переменные. Например, простейший интерфейс, который определяет все эти компоненты:

Interface IMovable { // константа const int minSpeed = 0; // минимальная скорость // статическая переменная static int maxSpeed = 60; // максимальная скорость // метод void Move(); // движение // свойство string Name { get; set; } // название delegate void MoveHandler(string message); // определение делегата для события // событие event MoveHandler MoveEvent; // событие движения }

В данном случае определен интерфейс IMovable, который представляет некоторый движущийся объект. Данный интерфейс содержит различные компоненты, которые описывают возможности движущегося объекта. То есть интерфейс описывает некоторый функционал, который должен быть у движущегося объекта.

Методы и свойства интерфейса могут не иметь реализации, в этом они сближаются с абстрактными методами и свойствами абстрактных классов. В данном случае интерфейс определяет метод Move, который будет представлять некоторое передвижение. Он не имеет реализации, не принимает никаких параметров и ничего не возвращает.

То же самое в данном случае касается свойства Name. На первый взгляд оно похоже на автоматическое свойство. Но в реальности это определение свойства в интерфейсе, которое не имеет реализации, а не автосвойство.

Еще один момент в объявлении интерфейса: если его члены - методы и свойства не имеют модификаторов доступа, но фактически по умолчанию доступ public , так как цель интерфейса - определение функционала для реализации его классом. Это касается также и констант и статических переменных, которые в классах и структурах по умолчанию имееют модификатор private. В интерфейсах же они имеют по умолчанию модификатор public. И например, мы могли бы обратиться к константе minSpeed и переменной maxSpeed интерфейса IMovable:

Static void Main(string args) { Console.WriteLine(IMovable.maxSpeed); Console.WriteLine(IMovable.minSpeed); }

Но также, начиная с версии C# 8.0, мы можем явно указывать модификаторы доступа у компонентов интерфейса:

Interface IMovable { public const int minSpeed = 0; // минимальная скорость private static int maxSpeed = 60; // максимальная скорость public void Move(); protected internal string Name { get; set; } // название public delegate void MoveHandler(string message); // определение делегата для события public event MoveHandler MoveEvent; // событие движения }

Начиная с версии C# 8.0 интерфейсы поддерживают реализацию методов и свойств по умолчанию. Это значит, что мы можем определить в интерфейсах полноценные методы и свойства, которые имеют реализацию как в обычных классах и структурах. Например, определим реализацию метода Move по умолчанию:

Interface IMovable { // реализация метода по умолчанию void Move() { Console.WriteLine("Walking"); } }

С реализацией свойств по умолчанию в интерфейсах дело обстоит несколько сложнее, поскольку мы не можем определять в интерфейсах нестатические переменные, соответственно в свойствах интерфейса мы не можем манипулировать состоянием объекта. Тем не менее реализацию по умолчанию для свойств мы тоже можем определять:

Interface IMovable { void Move() { Console.WriteLine("Walking"); } // реализация свойства по умолчанию // свойство только для чтения int MaxSpeed { get { return 0; } } }

Стоит отметить, что если интерфейс имеет приватные методы и свойства (то есть с модификатором private), то они должны иметь реализацию по умолчанию. То же самое относится к любым статическим методам и свойствам (не обязательно приватным):

Interface IMovable { public const int minSpeed = 0; // минимальная скорость private static int maxSpeed = 60; // максимальная скорость // находим время, за которое надо пройти расстояние distance со скоростью speed static double GetTime(double distance, double speed) => distance / speed; static int MaxSpeed { get { return maxSpeed; } set { if (value > 0) maxSpeed = value; } } } class Program { static void Main(string args) { Console.WriteLine(IMovable.MaxSpeed); IMovable.MaxSpeed = 65; Console.WriteLine(IMovable.MaxSpeed); double time = IMovable.GetTime(100, 10); Console.WriteLine(time); } }

Модификаторы доступа интерфейсов

Как и классы, интерфейсы по умолчанию имеют уровень доступа internal , то есть такой интерфейс доступен только в рамках текущего проекта. Но с помощью модификатора public мы можем сделать интерфейс общедоступным:

Public interface IMovable { void Move(); }

Стоит отметить, что в Visual Studio есть специальный компонент для добавления нового интерфейса в отдельном файле. Для добавления интерфейса в проект можно нажать правой кнопкой мыши на проект и в появившемся контекстном меню выбрать Add -> New Item... и в диалоговом окне добавления нового компонента выбрать пункт Interface .

Последнее обновление: 26.05.2019

В Xamarin.Forms визуальный интерфейс состоит из страниц. Страница представляет собой объект класса Page , она занимает все пространство экрана. То есть то, что мы видим на экране мобильного устройства - это страница. Приложение может иметь одну или несколько страниц.

Страница в качестве содержимого принимает один из контейнеров компоновки, в который в свою очередь помещаются стандартные визуальные элементы типа кнопок и текстовых полей, а также другие элементы компоновки.

Возьмем созданный в прошлой теме проект HelloApp (или создадим новый). По умолчанию весь интерфейс создается в классе App, который располагается в файле App.xaml.cs и который представляет текущее приложение:

Его код по умолчанию:

Using System; using Xamarin.Forms; using Xamarin.Forms.Xaml; namespace HelloApp { public partial class App: Application { public App() { InitializeComponent(); MainPage = new MainPage(); } protected override void OnStart() { // Handle when your app starts } protected override void OnSleep() { // Handle when your app sleeps } protected override void OnResume() { // Handle when your app resumes } } }

Работа класса App начинается с конструктора, где сначала вызывается метод InitializeComponent() , который выполняет инициализацию объекта, а потом устанавливается свойство MainPage . Через это свойство класс App устанавливает главную страницу приложения. В данном случае она определяется классом HelloApp.MainPage, то есть тем классом, который определен в файлах MainPage.xaml и MainPage.xaml.cs.

Но данный путь не единственный. Xamarin.Forms позволяет создавать визуальный интерфейс как с помощью кода C#, так и декларативным путем с помощью языка xaml, аналогично html, либо комбинируя эти подходы.

Создание интерфейса из кода C#

Добавим в проект HelloApp обычный класс на языке C#, который назовем StartPage .

И определим в этом классе следующее содержимое:

Using Xamarin.Forms; namespace HelloApp { class StartPage: ContentPage { public StartPage() { Label header = new Label() { Text = "Привет из Xamarin Forms" }; this.Content = header; } } }

Данный класс представляет страницу, поэтому наследуется от класса ContentPage . В конструкторе создается метка с текстом, которая задается в качестве содержимого страницы (this.Content = header).

Чтобы обозначить MainPage в качестве стартовой страницы, изменим класс App:

Using Xamarin.Forms; namespace HelloApp { public partial class App: Application { public App() { InitializeComponent(); MainPage = new StartPage(); } protected override void OnStart() { // Handle when your app starts } protected override void OnSleep() { // Handle when your app sleeps } protected override void OnResume() { // Handle when your app resumes } } }

Теперь свойство MainPage указывает на только что созданную страницу StartPage.

Также стоит отметить, что в Visual Studio есть готовый шаблон для добавления новых классов страниц с простейшим кодом. Так, чтобы добавить новую страницу, надо при добавлении нового элемента выбрать шаблон Content Page (C#) :

Данный класс добавляется в главный проект решения (в данном случае это HelloApp).

Добавленный класс страницы будет иметь следующий код:

Using System; using System.Collections.Generic; using System.Linq; using System.Reflection.Emit; using System.Text; using Xamarin.Forms; namespace HelloApp { public class Page1: ContentPage { public Page1() { Content = new StackLayout { Children = { new Label { Text = "Hello Page" } } }; } } }

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

И также в классе приложения мы можем установить эту страницу в качестве стартовой:

Using Xamarin.Forms; namespace HelloApp { public partial class App: Application { public App() { InitializeComponent(); MainPage = new Page1(); } //........... } }

1.1. Hello, Qt!

Ниже приводится текст простейшей Qt программы:

1 #include 2 #include 3 int main(int argc, char *argv) 4 { 5 QApplication app(argc, argv); 6 QLabel *label = new QLabel("Hello, Qt!", 0); 7 app.setMainWidget(label); 8 label->show(); 9 return app.exec(); 10 } Здесь, в строках 1 и 2, подключаются определения классов QApplication и QLabel .

В строке 5 создается экземпляр класса QApplication , который управляет ресурсами приложения. Конструктору QApplication передаются аргументы argc и argv , поскольку Qt имеет возможность обрабатывать аргументы командной строки.

В строке 6 создается визуальный компонент QLabel , который отображает надпись "Hello, Qt!". В терминологии Qt, все визуальные компоненты, из которых строится графический интерфейс, называются виджетами (widgets). Кнопки, меню, полосы прокрутки и разнообразные рамки -- все это виджеты. Одни виджеты могут содержать в себе другие виджеты, например, главное окно приложения -- это самый обычный виджет, который может содержать QMenuBar , QToolBar , QStatusBar и др. Аргумент 0, передаваемый конструктору QLabel (в строке 6) -- это "пустой" (null) указатель, который сообщает о том, что этот виджет не имеет "хозяина", т.е. не включается в другой виджет.

В строке 7 назначается "главный" виджет приложения. Когда пользователь закрывает "главный" виджет приложения (например, нажатием на кнопку "X" в заголовке окна), то программа завершает свою работу. Если в программе не назначить главный виджет, то она продолжит исполнение в фоновом режиме даже после того, как пользователь закроет окно.

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

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

Любое действие пользователя порождает событие (другими словами -- "сообщение"), в ответ на которое программа может вызвать одну или более функций. В этом смысле, приложения с графическим интерфейсом кардинально отличаются от обычных программ, с пакетной обработкой данных, которые приняв ввод от пользователя, они самостоятельно обрабатывают его, выдают результаты и завершают свою работу без дальнейшего участия человека.

Рисунок 1.1. Окно приложения в Windows XP


Теперь самое время проверить работу нашего приложения. Но прежде всего -- необходимо, чтобы у вас была установлена Qt 3.2 (или более поздняя версия), а переменная окружения PATH содержала корректный путь к каталогу bin . (В Windows настройка переменной PATH выполняется автоматически, в процессе установки библиотеки Qt)

Скопируйте текст программы в файл, с именем hello.cpp , в каталог hello .

Перейдите в этот каталог и дайте команду:

Qmake -project она создаст платформо-независимый файл проекта (hello.pro), а затем дайте следующую команду: qmake hello.pro Эта команда создаст Makefile , на основе файла проекта. Дайте команду make , чтобы скомпилировать программу и затем запустите ее, набрав в командной строке hello (в Windows) или ./hello (в Unix) или open hello.app (в Mac OS X). Если вы работаете в Windows и используете Microsoft Visual C++, то вместо команды make вы должны дать команду nmake . Как альтернативный вариант -- вы можете создать проект Visual Studio из файла hello.pro , запустив команду: qmake -tp vc hello.pro и затем скомпилировать программу в Visual Studio.

Рисунок 1.2. Метка с форматированным текстом.


А теперь немного развлечемся. Изменим внешний вид метки, добавив форматирование текста в стиле HTML. Для этого, замените строку

QLabel *label = new QLabel("Hello, Qt!", 0); на QLabel *label = new QLabel("

Hello " "Qt!

", 0); и пересоберите приложение.


1.2. Обработка сигналов.

Следующий пример показывает -- как организовать реакцию приложения на действия пользователя. Это приложение содержит кнопку, при нажатии на которую программа закрывается. Исходный текст очень похож на предыдущий пример, за исключением того, что теперь, в качестве главного виджета, вместо QLabel используется QPushButton , и добавлен код, который обслуживает факт ее нажатия.

Рисунок 1.3. Приложение Quit.


1 #include 2 #include 3 int main(int argc, char *argv) 4 { 5 QApplication app(argc, argv); 6 QPushButton *button = new QPushButton("Quit", 0); 7 QObject::connect(button, SIGNAL(clicked()), 8 &app, SLOT(quit())); 9 app.setMainWidget(button); 10 button->show(); 11 return app.exec(); 12 } Виджеты Qt имеют возможность посылать приложению сигналы , извещая его о том, что пользователь произвел какое-либо действие или о том, что виджет изменил свое состояние . Например, экземпляры класса QPushButton посылают приложению сигнал clicked() , когда пользователь нажимает на кнопку. Сигнал может быть "подключен" к функции-обработчику (такие функции-обработчики в Qt называются слотами ). Таким образом, когда виджет посылает сигнал, автоматически вызывается слот. В нашем примере мы подключили сигнал clicked() , от кнопки, к слоту quit() , экземпляра класса QApplication . Вызовы SIGNAL() и SLOT() -- это макроопределения, более подробно мы остановимся на них в следующей главе.

Теперь соберем приложение. Надеемся, что вы уже создали каталог quit и разместили в нем файл quit.cpp . Дайте команду qmake , для создания файла проекта, а затем второй раз -- для создания Makefile:

Qmake -project qmake quit.pro Теперь соберите приложение командой make и запустите его. Если вы щелкнете по кнопке "Quit" или нажмете на клавиатуре клавишу "Пробел", то приложение завершит свою работу.

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

Рисунок 1.4. Приложение Age.


Приложение содержит три виджета: QSpinBox , QSlider и QHBox (область горизонтальной разметки). Главным виджетом приложения назначен QHBox . Компоненты QSpinBox и QSlider помещены внутрь QHBox и являются подчиненными , по отношению к нему.

Рисунок 1.5. Виджеты приложения Age.


1 #include 2 #include 3 #include 4 #include 5 int main(int argc, char *argv) 6 { 7 QApplication app(argc, argv); 8 QHBox *hbox = new QHBox(0); 9 hbox->setCaption("Enter Your Age"); 10 hbox->setMargin(6); 11 hbox->setSpacing(6); 12 QSpinBox *spinBox = new QSpinBox(hbox); 13 QSlider *slider = new QSlider(Qt::Horizontal, hbox); 14 spinBox->setRange(0, 130); 15 slider->setRange(0, 130); 16 QObject::connect(spinBox, SIGNAL(valueChanged(int)), 17 slider, SLOT(setValue(int))); 18 QObject::connect(slider, SIGNAL(valueChanged(int)), 19 spinBox, SLOT(setValue(int))); 20 spinBox->setValue(35); 21 app.setMainWidget(hbox); 22 hbox->show(); 23 return app.exec(); 24 } В строках с 8 по 11 создается и настраивается QHBox . Чтобы вывести текст в заголовке окна, вызывается setCaption() . А затем устанавливается размер пустого пространства (6 пикселей) вокруг и между подчиненными виджетами.

В строках 12 и 13 создаются QSpinBox и QSlider , которым, в качестве владельца, назначается QHBox .

Не смотря на то, что мы явно не задали ни положение, ни размеры виджетов QSpinBox и QSlider , тем менее они очень аккуратно расположились внутри QHBox . Собственно для этого и предназначен QHBox . Он выполняет автоматическое размещение подчиненных виджетов, назначая им координаты размещения и размеры, в зависимости от их требований и собственных настроек. В Qt имеется много классов, подобных QHBox , которые избавляют нас от рутинной работы по ручной подгонке положения и размеров визуальных компонентов.

В строках 14 и 15 устанавливаются допустимые пределы изменения счетчика и ползунка. (Мы можем смело предположить, что возраст нашего пользователя едва ли превысит 130 лет.) Два вызова connect() , в строках с 16 по 19 синхронизируют ползунок и счетчик, благодаря чему они всегда будут отображать одно и то же значение. Всякий раз, когда значение одного из виджетов изменяется, он посылает сигнал valueChanged(int) , который поступает в слот setValue(int) другого виджета.

В строке 20 устанавливается первоначальное значение (35) счетчика. Когда это происходит, счетчик посылает сигнал valueChanged(int) , со значением входного аргумента, равным 35. Это число передается в слот setValue(int) виджета QSlider , который устанавливает значение этого виджета равным 35. После этого уже QSlider посылает сигнал valueChanged(int) , поскольку его значение только что изменилось, вызывая таким образом слот setValue(int) виджета QSpinBox . Но на этот раз счетчик не посылает сигнал, поскольку его значение и так было равно 35. Таким образом предотвращается бесконечная рекурсия. Рисунок 1.6 иллюстрирует эту ситуацию.

Рисунок 1.6. Изменение одного значения вызывает изменение другого.


В строке 22 QHBox делается видимым (вместе со всеми подчиненными виджетами).

Подход к формированию интерфейса в Qt очень прост для понимания и чрезвычайно гибок. В общем случае, программист выбирает необходимые ему виджеты, размещает их внутри областей выравнивания (layouts), которые в свою очередь принимают на себя обязанности по размещению виджетов, и настраивает свойства виджетов. На заключительном этапе устанавливаются взаимосвязи виджетов, через механизм сигналов и слотов, которые обусловливают поведение пользовательского интерфейса.

1.3. Работа со справочной системой.

Справочная система в Qt -- это пожалуй самый основной инструмент любого разработчика. Она описывает все классы и функции в этой библиотеке. (Документация к Qt 3.2 включает в себя описанее более 400 классов и 6000 функций.) В этой книге вы встретитесь с большим количеством классов и функций Qt, но далеко не со всеми. Поэтому совершенно необходимо, чтобы вы самостоятельно ознакомились со справочной системой Qt.

Стили виджетов
Скриншоты, которые мы до сих пор видели, были получены в Windows XP. Однако внешний вид виджетов изменяется, в зависимости от платформы, на которой запускается приложение. С другой стороны, Qt в состоянии эмулировать внешний вид любой из поддерживаемых платформ.



В этой статье речь пойдет о создании простейших приложений с использованием форм на языке C++. Сразу хочу внести ясность: разработка «формовых» С++ приложений будет осуществляться в среде Microsoft Visual Studio (обойдем стороной главного конкурента от компании Borland Software). Стоит отметить, что в Visual Studio есть два способа сделать приложение с формами, решение принимается в момент создания нового проекта.

Первый из них - использовать Windows Forms, реализующий графический интерфейс пользователя и входящий в Microsoft.NET Framework. Данный подход упрощает доступ к интерфейсным элементам Microsoft Windows благодаря созданию обёртки для Win32 API в управляемом коде. Если изложить свои мысли в более понятной форме, то данный подход очень схож с построением консольного приложения, но чуть более сложен т.к. использует формы.

Второй способ основан на использовании Microsoft Foundation Classes (MFC), библиотеке, которая берет на себя заботу о создании каркаса приложения. В отличие от первого, MFC «из коробки» использует патерн MVC (Model-View-Cont roller). Данный подход сложнее первого, но опираясь на него можно запросто создать каркас для весьма интересных приложений, к примеру, текстового редактора или использовать компонент Ribbon и сделать меню как в небезызвестном MS Office 2010.

Создание приложения в MS Visual Studio

Давайте создадим новое приложение: File->New->Project. В появившемся окне как на рисунке выше найдите и выберите Windows Forms Application, далее укажите название (app1) и расположение нового проекта и подтвердите его создание нажатием кнопки «OK».

Прежде чем приступить непосредственно к программированию, следует понять, что такое событие. Событие это действие, которое происходит при определённых условиях. Самыми простыми (и наиболее распространенным и) можно считать Load,Click… рассмотрим некоторые из них более подробно:

  • Activated - событие, возникающее при активизации элемента.
  • Click - возникает при одиночном нажатии на элемент.
  • DoubleClick - двойной щелчок по элементу.
  • HelpRequested - срабатывает при нажатии клавиши .
  • Paint - возникает, когда элемент перерисовывается.
  • MouseLeave - событие срабатывает, когда курсор покидает границы элемента.

Не стоит забывать, что свойственные элементу события зависят от его типа. Чтобы просмотреть все доступные для объекта формы события следует выделить его и в окне свойств выбрать значок молнии. Ниже показана часть событий для элементаForm1. Как можете видеть для события Load выбрана функция Form1_Load, следовательно код, содержащийся в этой функции будет вызван при загрузке формы.

Откройте файл Form1.h, там будет такой код:

Private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e){ }

Это та самая функция Form1_Load, срабатывающая при загрузке формы. Давайте убедимся в этом, добавив на форму компонент TextBox.

Для этого откройте ресурс формы и выделите его. Далее выберите панель с инструментами Toolbox и перетащите компонент TextBox на форму. Модифицируйте функцию Form1_Load следующим образом:

Private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { textBox1->Text = "Hello, World!"; //textBox1 – имя добавленного вами текст бокса }

Запустите проект, в итоге должно появиться следующее сообщение:

На этом пока все, продолжение в следующих уроках.

Понравилась статья? Поделиться с друзьями: