Програма c з графічним інтерфейсом. Створення графічного інтерфейсу засобами Qt. Створення інтерфейсу із коду C#

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 та ін. 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 = новий 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 = новий QPushButton("Quit", 0); 7 QObject::connect(button, SIGNAL(clicked() ), 8 &app, SLOT(quit())), 9 app.setMainWidget(button);10 button->show(); сигнали, сповіщаючи його про те, що користувач справив будь-яку дію або про те, що віджет змінив свій стан. Наприклад, екземпляри класу 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 = новий 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 ); 15 slider->setRange(0, 130); 16 QObject::connect(spinBox, SIGNAL(valueChanged(int)), 17 slider, SLOT(setValue(int))); (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 – ім'я доданого вами текст боксу )

Запустіть проект, у результаті має з'явитися таке повідомлення:

На цьому поки що все, продовження в наступних уроках.

Останнє оновлення: 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; використовуючи System.Collections.Generic; using System.Linq; використовуючи 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(); ) //........... ) )

5

Я зробив багато різних розділів GUI-системи для Nintendo DS, таких як кнопки та текстові поля та прапорці, але мені потрібен спосіб приховати ці класи в одному класі Gui, щоб я міг малювати все на екрані все відразу, і одразу перевірте всі кнопки, щоб перевірити, чи натиснуто будь-які кнопки. Моє питання - як найкраще організувати всі класи (наприклад, кнопки та текстові поля) в один GUI-клас?

Ось один спосіб, яким я думав, але це не здається правильним:

Edit:Я використовую C++.

Class Gui ( public: void update_all(); void draw_all() const; int add_button(Button *button); // Returns button id void remove_button(int button_id); private: Button *buttons; int num_buttons; )

Цей код має кілька проблем, але я просто хотів дати вам уявлення про те, що я хочу.

  • 5 відповідей
  • Сортування:

    Активність

2

Це питання дуже схоже на те, що я збирався публікувати, тільки моє призначене для програмування Sony PSP.

Я якийсь час щось шукав, я консультувався з деякими книгами та VTMs, і досі це є приблизна ідея простих систем ui.

Class uiElement() ( ... virtual void Update() = 0; virtual void Draw() = 0; ... ) class uiButton() public: uiElement ( ... virtual void Update(); virtual void Draw() ; ... ) class uiTextbox() public: uiElement ( ... virtual void Update(); virtual void Draw(); ... ) ... // Other ui Elements class uiWindow() ( ... void Update (); void Draw(); void AddElement(uiElement *Element); void RemoveElement(uiElement *Element); std::list Elements; ... ) void uiWindow::Update() ( ... for (list ::iterator it = Elements.begin(); it! = Elements.end(); it++) it->Update(); ... ) void uiWindow::Draw() ( ... for (list ::iterator it = Elements.begin(); it! = Elements.end(); it++) it->Draw(); ... )

princple є створення вікна і attact елементів інтерфейсу користувача до нього, і викликати малюнки та оновлення методи з відповідних основних функцій.

У мене поки що нічого не працює, тому що у мене проблеми з кодом малювання. З різними API-інтерфейсами на ПК та PSP я переглядаю код оболонки для OpenGL та psp gu.

Надіюсь це допоможе.

0

Одна корисна стратегія, яку слід пам'ятати, може бути composite pattern . На низькому рівні він може дозволити вам легше обробляти всі об'єкти GUI (та колекції об'єктів) після їх створення. Але я не знаю, що пов'язано з дизайном графічного інтерфейсу GUI, тому одне місце, щоб знайти спільне натхнення, це вихідний код існуючого проекту. WxWidgets – це крос-платформний графічний інтерфейс з доступним вихідним кодом. Удачі з вашим проектом!

0

3

Для тих, хто зацікавлений, ось мій з відкритим вихідним кодом, BSD-ліцензовані GUI інструментарій для DS:

Відповідь на предмет2k досить хороша, але я б серйозно рекомендував мати код, що містить елементи дочірнього інтерфейсу в базовому класі uiElement. Це зразок, за яким я стежив у Вупсі.

Якщо ви непідтримайте це в базовому класі, ви зіткнетеся з серйозними проблемами при спробі реалізувати щось складніше, ніж текстове поле та кнопку. Наприклад:

  • Табличні панелі можна змоделювати як кілька кнопок, згрупованих в єдиний батьківський елемент інтерфейсу користувача, який забезпечує взаємну винятковість вибору;
  • Групи радіостанцій (з часом);
  • Смуги прокручування можуть бути представлені як елемент слайдера/жолоба та кнопки вгору/вниз;
  • Списки прокручування можуть бути представлені у вигляді контейнера і декількох елементів інтерфейсу користувача.

Крім того, варто пам'ятати, що DS має процесор з частотою 66 МГц і 4 МБ ОЗУ, який використовується як для зберігання вашої програми, так і для її виконання (DS-диски завантажуються в ОЗУ до їх запуску). Ви дійсно повинні розглядати його як вбудовану систему, що означає, що STL немає. Я видалив STL з Woopsi та зумів зберегти 0.5MB. Не так багато за настільними стандартами, але це 1/8 загальної доступної пам'яті DS, споживаної STL-сміттям.

Я докладно весь процес написання інтерфейсу користувача на моєму блозі:

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

Windows 7