Привіт усім.
В даній статті розповідається про планетарно відомий кросплатформенний фереймворк графічних інтерфейсів для користувачів віконних програм- Qt. Основна мова програмування на якій і під яку розроблявся Qt - це C++. Але існують бібліотеки-адаптори для інших мов програмування на подобі Java, Python, C#, Node.js, PHP, Ruby і інші.
З-поміж усього іншого, візуальний фреймворк Qt відомий своїм використанням у GNU/Linux ОС-дистрибутивах на базі віконної системи KDE. Віконна система KDE, реалізована з використанням фреймворку Qt, надає користувачу повне функціональне віконне середовище для роботи і відпочинку з великою кількістю програм таких як Веб-браузери, офісні пакети і багато іншого.
Документація і домашня сторінка фреймворку
Сайт координаторів і розробників Qt знаходиться за адресою https://www.qt.io/. На ньому можна знайти документацію по Qt а також іншим розробкам компанії.
Історію створення фреймворку можна прочитати на Вікіпедії за адресою https://uk.wikipedia.org/wiki/Qt.
Деталі і вступ про Qt можна знайти на сторінці офіційної документації https://doc.qt.io/qt-6/qt-intro.html.
Дзеркало репозиторіїв на GitHub розміщено за адресою https://github.com/qt. Саме Qt 5 версії знаходиться за адресою https://github.com/qt/qt5.
Способи розробки
Qt підтримує декілька типів створення і збирання програм з вихідного джерельного коду. А саме:
- Створення і збирання програм за допомогою QtCreator - IDE від розробників Qt.
- Створення програми за допомогою QML і Qt Quick;
- Компіляція проекту за допомогою qmake;
- Компіляція проекту за допомогою інших засобів на подобі cmake і стандартного make.
У даній статті ми будемо використовувати стандартні засоби збирання проектів - cmake і звичайний make разом з Makefile-ами.
Віджети візуальної системи
На сайті документації по візульній системі Qt розміщено майже 200 класів для візуальної системи. Їх можна переглянути за посиланням https://doc.qt.io/qt-6/qtwidgets-module.html.
Онсовні віджети для створення вікон являються QApplication для запуску циклу обробки подій і QMainWindow для відображення головного вікна програми. Приклади використання будуть розміщені у секції прикладів.
Основними віджетами які вставляються у примірник класу QMainWindow головного вікна програми можуть бути:
- QLineEdit для введення і відображення інформації.
- QLabel для відображення текстової і графічної інформації на вікні.
- QPushButton для створення командних кнопок для виконання певних дій.
- QRadioButton для створення прапорців для вибору єдиного з множини.
- QCheckBox для створення прапорців опцій
- QMenuBar, QMenu і QAction - використовуються для побудови головного меню програми, розміщеного у верхній частині вікна.
- QTextEdit віджет для введення, редагування і відображення багаторядкової текстової інформації.
- QFileDialog доволяє користувачу обрати файл на доступних носіях.
- QInputDialog довзоляє користувачу ввести певну інформацію по запиту програми.
- QMessageBox віджет дозволяє створювати модальні діалогові вікна для інформування користувача.
- QStatusBar, який використовується для відображення статусу у нижній частині вікна програми (разом з QLabel). І багато інших.
На сторінках офіційної документації до відповідних класів можна знайти список підтримуваних методів і детальну інформацію до них.
За допомогою Qt також можна писати кросплатформенні програми без відображення вікон.
Приклади
Хоча у прикладах використовуються дві системи побудови для наглядності - CMake і Unix Makefile-ли, у випадку не Unix-подібної системи краще використовувати саме CMake систему. Оскільки CMake являється кросплатформенною системою генерації скриптів побудови, більш ймовірно що проект буде успішно зібрано у системі яка використовується.
Приклад #1 - як показати вікно
Розглянемо простий приклад використання QApplication і QMainWindow для показу пустого вікна на екран користувача. Даний приклад можна використовувати як базу для створення довільних вікон. Тому код з даного прикладу буде використовуватись і для інших прикладів.
Репозиторій з усіма файлами
Усі файли проекту можна переглянути за посиланням https://github.com/yuriysydor1991/kytok.org.ua-Qt-intro-resources/tree/main/basic-window, що знаходиться у GitHub репозиторію проекту-демонстрації для даної статті за посиланням https://github.com/yuriysydor1991/kytok.org.ua-Qt-intro-resources/tree/main. Увесь код проекту можна завантажити за допомогою команди git:
# якщо git ще не встановлено у системі sudo apt-get install -y git git clone https://github.com/yuriysydor1991/kytok.org.ua-Qt-intro-resources.git
Клас ArbitraryWindow
Спочатку необхідно оголосити головний клас вікна, який являє собою дочірній від того самого QMainWindow. Назвемо цей клас ArbitraryWindow. В загальному його оголошення може виглядати наступним чином:
#ifndef ARBITRARYWINDOW_H
#define ARBITRARYWINDOW_H
// підключаємо оголошення класу QMainWindow
#include <QMainWindow>
/*
* Створюємо клас довільного вікна ArbitraryWindow
* для відображення на екрані.
*/
class ArbitraryWindow:
// обов'язково потрібно вказати клас QMainWindow
// у якості батьківського класу
public QMainWindow
{
// обов'язковий виклик макросу!
Q_OBJECT
public:
ArbitraryWindow();
private slots:
private:
};
#endif //ARBITRARYWINDOW_H
Необхідно звернути увагу на обов'язковий макрос Q_OBJECT який використано всередині тіла оголошення класу QMainWindow. Без даного макросу вікно може не реагувати на події користувача.
Визначення класу, в даному випадку, - тривіальне, тому не будемо на ньому зупинятись.
Головна функція C++ програми
Далі можна поглянути на головну функцію програми - main. Вона може виглядати наступним чином:
#include <QApplication>
#include "ArbitraryWindow.h"
// головна функція C++ програми
int main (int argc, char** argv)
{
// створюємо обробник подій
QApplication eventLoop(argc, argv);
// створюємо примірник головного вікна
ArbitraryWindow justAWindow;
// показуємо вікно на екран
justAWindow.show();
//запускаємо цикл обробки подій вікон
return eventLoop.exec();
}
Даний файл розміщений за посиланням https://github.com/yuriysydor1991/kytok.org.ua-Qt-intro-resources/blob/main/basic-window/main.cpp.
Компіляція або збирання проекту
Даний проект можна скомпілювати декількома способами, а саме за допомогою системи генерації скриптів побудови CMake, або самою програмою побудови make.
Збирання за допомогою CMake
Щоб зібрати даний проект необхідно виконати наступні команди у командному рядку Linux, або будь-якої іншої підтримуваної ОС:
mkdir -vp build cd build cmake ../ cmake --build .
Вивід може виглядати наступним чином:
Збирання за допомогою Makefile
Скрипт Makefile який спроможний зібрати просте вікно на Qt5, може виглядати наступним чином:
CXXFLAGS=-g -Wall -Werror \ -I build/ -I window/ \ `pkg-config --cflags Qt5Widgets` \ `pkg-config --cflags Qt5Core` QTLIBS=`pkg-config --libs Qt5Widgets` \ `pkg-config --libs Qt5Core` debug: mkdir -vp build moc window/ArbitraryWindow.h -o build/ArbitraryWindow.moc.h c++ -c -fPIC $(CXXFLAGS) window/ArbitraryWindow.cpp -o build/ArbitraryWindow.cpp.o c++ -c -fPIC $(CXXFLAGS) main.cpp -o build/main.cpp.o c++ -o build/Qt5BasicMainWindow build/main.cpp.o build/ArbitraryWindow.cpp.o $(QTLIBS) clean: rm -fr build rm -f *.o
Даний скрипт розміщено за адресою https://github.com/yuriysydor1991/kytok.org.ua-Qt-intro-resources/blob/main/basic-window/Makefile.
І щоб скомпілювати демо-вікно за допомогою даного Makefile-скрипта необхідно скористатись наступними командами для командного інтерпретатора Linux чи іншої Unix-подібної ОС (вводити з кореня проекту):
cd basic-window/ make clean debug
Вивід може виглядати наступним чином:
Фінальний результат
Після компіляції обома способами і запуску програми на екрані можна побачити наступне вікно:
Приклад #2 - вікно з меню
Розглянемо приклад не складного вікна з меню, яке показує модальне діалогове вікно при натисканні на один елемент субменю.
Усі файди прикладу можна знайти у директорії за адресою https://github.com/yuriysydor1991/kytok.org.ua-Qt-intro-resources/tree/main/window-with-menu GitHub репозиторію, що знаходиться за адресою https://github.com/yuriysydor1991/kytok.org.ua-Qt-intro-resources/tree/main.
Оголошення і визначення класу WindowWithMenu
Спочатку оголошуємо клас WindowWithMenu, який являється дочірнім від QMainWindow. Повний приклад оголошення можна знайти за посиланням https://github.com/yuriysydor1991/kytok.org.ua-Qt-intro-resources/blob/main/window-with-menu/window/WindowWithMenu.h з репозиторію прикладів для даної статті за адресою https://github.com/yuriysydor1991/kytok.org.ua-Qt-intro-resources/tree/main.
// підключаємо оголошення класу QMainWindow
#include <QMainWindow>
/*
* Створюємо клас вікна з меню WindowWithMenu
* для відображення на екрані.
*/
class WindowWithMenu:
// обов'язково потрібно вказати клас QMainWindow
// у якості батьківського класу
public QMainWindow
{
// обов'язковий виклик макросу!
Q_OBJECT
public:
// конструктор у якому створюється меню
WindowWithMenu();
private slots:
// метод-слот для меню "Сказати привіт"
void sayHello();
private:
};
Після чого можна визначити конструктор класу WindowWithMenu, який буде створювати і упаковувати об'єкти меню, а також метод sayHello, котрий показуватиме модальне інформаційне вікно з текстом, використовуючи клас-віджет QMessageBox. Повний приклад реалізації методів можна переглянути за посиланням https://github.com/yuriysydor1991/kytok.org.ua-Qt-intro-resources/blob/main/window-with-menu/window/WindowWithMenu.cpp. Реалізація може виглядати наступним чином:
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QMessageBox>
WindowWithMenu::WindowWithMenu()
{
// створюємо меню "Програма" на панелі меню
auto fileMenu = menuBar()->addMenu(tr("Програма"));
// свтрюємо елемент субменю "Сказати привіт"
auto hello = fileMenu->addAction(tr("Сказати привіт"));
// поєднюємо меню з конкретним методом-слотом
// класу sayHello
connect(hello, SIGNAL(triggered()), this, SLOT(sayHello()));
}
void WindowWithMenu :: sayHello()
{
// код, який показує віконечко з привітом ;)
QMessageBox::information(
this,
tr("Привіт"),
tr("Привіт, Планета!")
);
}
Як видно з коду, в реалізації класу присутні два методи - конструктор і sayHello. У самому конструкторі виконуються побудова дерева меню вікна за допомогою методів addMenu (для елементів які розкриваються з панеллю) чи addAction (для самих елементів меню, які виконують певні дії). У нашому випадку слот-метод sayHello викликає статичний метод з класу QMessageBox для показу інформаційного вікна з привітанням.
Головна функція програми виглядає так само як і в попередньому прикладі, за виключенням використаного файлу підключення і класу створеного примірника вікна. Детальніше можна переглянути за адресою https://github.com/yuriysydor1991/kytok.org.ua-Qt-intro-resources/blob/main/window-with-menu/main.cpp.Побудова проекту класу WindowWithMenu - Qt5WindowWithMenu
Щоб побудувати проект для вікна з меню, небхідно склонувати його репозиторій на локальну машину за допомогою команд
# якщо git ще не встановлено у системі sudo apt-get install -y git git clone https://github.com/yuriysydor1991/kytok.org.ua-Qt-intro-resources.git
Наступним кроком буде використання CMake для побудови бінарного виконуваного файлу з вихідного джерельного коду за допомогою команд:
cd kytok.org.ua-Qt-intro-resources/ mkdir -vp build cd build cmake ../ cmake --build . --target Qt5WindowWithMenu
Вивід у командний рядок може виглядати наступним чином:
Як альтернативний спосіб побудови можна використати стандартну Unix-команду make разом з створеним файлом Makefile вміст якого можна переглянути за адресою https://github.com/yuriysydor1991/kytok.org.ua-Qt-intro-resources/blob/main/window-with-menu/Makefile. Команди командного рядка для побудови наступні (з кореню проекту https://github.com/yuriysydor1991/kytok.org.ua-Qt-intro-resources/tree/main):
cd window-with-menu/ make clean debug
Вивід може виглядати наступним чином:
Результат успішної збірки і запуску програми буде приблизно наступний:
Після натискання на елемент меню:
Приклад #3 - вікно з кнопкою, полем для вводу і прапорцями
В даному прикладі розглянемо нескладне вікно з декількома елементами у ньому: поле для вводу імені QLineEdit або довільного тексту, QPushButton для ініціювання взаємодії і два взаємовиключаючі прапорця для вказування типу взаємодії.
Усі файди прикладу можна знайти у директорії за адресою https://github.com/yuriysydor1991/kytok.org.ua-Qt-intro-resources/tree/main/button-with-hello GitHub репозиторію, що знаходиться за адресою https://github.com/yuriysydor1991/kytok.org.ua-Qt-intro-resources/tree/main.
Оголошення і визначення класу HelloButtonWindow
Оголошення класу HelloButtonWindow може виглядати наступним чином:
// підключаємо оголошення класу QMainWindow
// і інші необхідні класи
#include <QMainWindow>
#include <QRadioButton>
#include <QLineEdit>
/*
* Створюємо клас вікна HelloButtonWindow
* для відображення на екрані.
*/
class HelloButtonWindow:
// обов'язково потрібно вказати клас QMainWindow
// у якості батьківського класу
public QMainWindow
{
// обов'язковий виклик макросу!
Q_OBJECT
public:
HelloButtonWindow();
private slots:
void interact();
private:
QRadioButton* hello;
QLineEdit* edit;
};
Повний файл оголошення класу можна переглянутиз а адресою GitHub репозиторію https://github.com/yuriysydor1991/kytok.org.ua-Qt-intro-resources/blob/main/button-with-hello/window/HelloButtonWindow.h.
Після чого сама реалізація класу насутпна:
// підключаємо згенерований moc-програмою
// заголовковий файл
#include "HelloButtonWindow.moc.h"
#include <QHBoxLayout<
#include <QPushButton>
#include <QLineEdit>
#include <QFrame>
#include <QRadioButton>
#include <QMessageBox>
HelloButtonWindow::HelloButtonWindow():
hello{nullptr}, edit{nullptr}
{
// будуємо вікно взаємодії
auto frame = new QFrame ;
setCentralWidget(frame);
auto button = new QPushButton(tr("Взаємодія"));
edit = new QLineEdit;
auto form = new QHBoxLayout;
auto bye = new QRadioButton(tr("попрощатись"));
hello = new QRadioButton(tr("привітатись"));
frame->setLayout(form);
form->addWidget(edit);
form->addWidget(button);
form->addWidget(bye);
form->addWidget(hello);
connect(button, SIGNAL(clicked()), this, SLOT(interact()));
hello->setChecked(true);
setWindowTitle(tr("Вікно взаємодії"));
}
void HelloButtonWindow::interact()
{
//обчислюємо префікс взаємодії
auto interactionText = hello->isChecked()
? tr("Привіт")
: tr("До побачення") ;
//отримуємо введений текст
auto text = edit->displayText();
interactionText += ", " + text + "!";
if (text.isEmpty()) {
// якщо відсутній текст - показати попередження
QMessageBox::warning(
this,
tr("Помилка"),
tr("Введіть ім'я!")
);
return ;
}
// код, який показує віконечко з взаємодією ;)
QMessageBox::information(
this,
tr("Взаємодія"),
interactionText
);
}
Повністю файл реалізації класу HelloButtonWindow можна переглянути за адресою https://github.com/yuriysydor1991/kytok.org.ua-Qt-intro-resources/blob/main/button-with-hello/window/HelloButtonWindow.cpp.
Побудова проекту
Щоб побудувати виконуваний файл для класу HelloButtonWindow за допомогою CMake, необхідно скористатись наступними командами (з кореня проекту):
mkdir -vp build cd build cmake ../ cmake --build . --target Qt5HelloButtonWindow
Що у командному рядку GNU/Linux заснованої ОС Linux Mint може виколядати наступним чином:
У якості альтернативи, для наглядності, можна скористатись стандартом для Unix-подібних систем Makefile-ом і командою make у командному рядку (з кореня поректу):
cd button-with-hello/ make clean debug
Запуск прикладу
Після успішної побудови і запуску виконуваного файлу даного прикладу, на екрані можна побачити наступне:
Після введення тексту у поле для вводу і натискання відповідної кнопки, можна побачити наступне:
Приклад текстового редактора
Приклад тривіального редактора текстових файлів реалізованого з використанням Qt5 C++ і CMake (також з іншими технологіями) можна переглянути за адресою GitHub репозиторію https://github.com/yuriysydor1991/Qt1SimpleTextEditor.
Офіційні приклади від розробників Qt
З-поміж усього іншого розробники Qt предоставляють власні приклади використання даної візуальної системи. Доступні приклади для різних версій фреймворку. Також присутні приклади не тільки для настільних комп'ютерів, а й також для інших платформ.
Для Qt версії 5.15 LTS вони доступні за адресою https://doc.qt.io/qt-5/qtexamplesandtutorials.html.
Для версії 6.6 LTS приклади доступні за адресою https://doc.qt.io/qt-6.5/qtexamplesandtutorials.html.