Емельянова, Д. К. Разработка программы калькулятор в программном пакете QT / Д. К. Емельянова, А. М. Максимова. — Текст : непосредственный // Молодой ученый. — 2016. — № 20 (124). — С. 147-148. — URL: https://moluch.ru/archive/124/34334/ (дата обращения: 12.07.2023).
Ключевые слова: объектно-ориентированное программирование, QT, классы, калькулятор
Людям, делающим свои первые шаги в объектно-ориентированное программирование, полезно и крайне удобно делать это в программном пакете QT. В этой статье будет рассмотрена работа в QT на примере простейшего проекта — «Калькулятор».
QT — это кроссплатформенный фреймворк, который позволяет запустить программное обеспечение в любой операционной системе без изменения исходного кода. Также QT включает в себя множество полезных классов для работы с различными объектами, базами данных, графическим интерфейсом и многое другое, что сокращает объём работы. QT имеет множество и других полезных особенностей.
Проект калькулятор будет являться приложением QtWidgets, такой пункт и следует выбрать при создании проекта. После того как в диалоговом окне введены название проекта и путь, выбрать тип базового класса, который будет создан автоматически. Для проекта «Калькулятор» выберем тип QWidget, т. к. работа будет происходить непосредственно в главном окне, без использования строки меню, или панели инструментов, или всплывающих окон.
Qt дизайн. Дизайн приложений QtWidgets на примере создания игры Крестики-нолики. Часть 1
После создания проекта автоматически в нем будут созданы файлы:.срр, файлы главной функции и базового класса, heder базового класса и ui-форма. Написание проекта начинается в ui-форме — это окно, в котором можно создать внешний вид нашего проекта.
В созданной ui-форме надо расположить в нужном порядке необходимые компоненты визуальной составляющей проекта. Выберем в окне слева поле для ввода/вывода информации LineEdit и необходимое количество кнопок. Двойным нажатием на кнопку можно менять надпись на выбранной кнопке. Для калькулятора необходимо иметь кнопки с цифрами от 0 до 9, кнопки с простейшими операциями умножения, сложения, деления, вычитания, кнопки с такими операциями, как: возведение в степень, натуральный логарифм, синус и косинус, кнопка «=» для вывода результата операции и пара необходимых для любого калькулятора кнопок: стереть всё и стереть символ слева. Для того, чтобы код был понятным для любого пользователя, в свойствах любого объекта можно изменить его стандартное имя на более подходящее, например: Button_answer вместо pushButton_9.
Перейдем к самой программе. В heder файле необходимо объявить две переменные типа double и перечисление Operation, содержащее имена операций. В файле.срр опишем работу кнопок. Функции для описания работы кнопок по нажатию создаются после выполнения следующих действий: на ui-форме кликнуть ПКМ по нужной кнопке, во всплывающем окне выбрать «Перейти к слоту».. и выбрать сигнал clicked().
Функция для одной кнопки будет создана автоматически в файле calculator.cpp. Аналогичную операцию стоит провести со всеми имеющимися кнопками.
Простой GUI калькулятор на Python #1. Дизайн приложения
Стоит обратить внимание на разницу между оператором двойного двоеточия и точкой. Оператор двойного двоеточия отделяет имя класса от имени его члена или функции, а оператор точка отделяет имя экземпляра класса от имени его члена или функции.
Теперь опишем функции кнопок. Для кнопок с цифрами будем выводить в поле ввода/вывода информации цифру с кнопки. Вот пример функции для кнопки с единицей.
По нажатию на кнопки с простейшими арифметическими операциями, запишем в первую переменную типа double число, содержащееся в поле ввода/вывода информации, присвоим перечислению operation значение, соответствующее назначению кнопки и очистим поле ввода/вывода информации LineEdit. Пример функции для кнопки с назначением сложения:
Как можно заметить, по нажатию на кнопку с операцией, пока не производит самого вычисления, это мы оставили кнопке вывода результата. В её функции пропишем присваивание значения второй переменной типа double, объявим новую переменную для записи результата и, используя оператор ветвления switch, пропишем операции для получения результата для каждого значения перечисления operation. Затемвыведемполученныйответ.
Источник: moluch.ru
О Многопоточности в Qt и как создать поток
Многопоточность — свойство платформы выполнять код внутри одного процесса может выполнятся “параллельно” без предписанного порядка во времени. Такой подход полезен когда отделить ресурсоёмкую задачу от остального кода. Например, читать с диска в память большой файл и не «заморозить» графический интерфейс программы. В этой статье поговорим о многопоточности в C++ и о том, как это работает во фреймворке Qt. На примере покажу как запустить в отдельном потоке только один метод объекта, оставив остальные методы «снаружи», обсудим плюсы и минусы такого подхода и как поступить в такой ситуации!
Содержание статьи 1. Как устроена многопоточность в Qt? 2. Создание потока через обертку 3. Переопределение метода run() класса QThread 4. Достоинства и недостатки
1. Как устроена многопоточность в Qt?
В Qt потоками управляет класс QThread.
Он представляет собой обёртку для потоков операционной системы и предоставляет кросс-платформенный интерфейс для работы с ними.
Помните, что один объект отвечает за один поток, поэтому не стоит бездумно плодить потоки. Создание потока сопряжено с существенными накладными расходами в программе.
Запустить код в отдельном потоке можно двумя способами:
- создание обёртки для нашего класса, который будет жить в отдельном потоке;
- переопределение метода run() в унаследованном от QThread классе.
Важно! Выделение памяти оператором new для экземпляров класса необходимо выполнять в том потоке, в котором они будут исполнятся.
Это правило делает собственником объектов тот поток, который их создал. Так легче контролировать жизненный цикл объектов и позволит избежать ошибок в работе, когда используемый объект внезапно был удален в другом потоке.
2. Создание потока через обёртку
Допустим, что вся тяжелая работа выполняется в методе doWork() класса HeavyWork, поэтому необходимо перенести его в отдельный поток. Код класса представлен ниже:
#include class HeavyWork : public QObject < Q_OBJECT public: void doWork() < std::cout >;
Экземпляр такого класса необходимо создать внутри потока. Напрямую сделать этого не возможно, поэтому создадим обработчик, который и будет создавать, взаимодействовать и уничтожать такой объект. Создаем класс Worker с одним методом и сигналом, излучаемым с флагом типа bool, оповещающем об (не) успешности выполненной работы. Все это происходит внутри метода process():
#include class Worker : public QObject < Q_OBJECT HeavyWork* work; public slots: void process(); signals: void finished(bool); >; void Worker::process() < // Этот метод будет запущен при старте потока // Аллоцируем наш объект. Теперь это происходит в отдельном потоке work = new HeavyWork(); if(work == nullptr) < // Если произошла ошибка, то сигнализируем что поток завершен с отрицательным результатом и покидаем функцию (а с ней и завершается поток) emit finished(false); return; >// Делаем сложную работу work->doWork(); // Сигнализируем об успешном выполнении emit finished(true); >
На этом подготовительные операции выполнены и переходим к перемещению обработчика Worker в отдельный поток. Для этого создадим ещё один объект Controller, внутри которого вся магия и произойдет: экземпляр обработчика Worker и поток начнут взаимодействовать.
class Controller : public QObject < Q_OBJECT public: void makeThread(); >;
Единственный метод класса – makeThread(), вот он то нам и нужен, давайте его пошагово реализуем!
- Создаем экземпляры обработчика Worker и экземпляр потока QThread
Worker* worker = new Worker(); QThread* thread = new QThread();
2. Настроим и передадим данные, если нужно, экземпляру Worker. В этой точке у нас есть последний шанс сделать это привычным путем
3. Перемещаем worker в новорожденный поток
worker->moveToThread(thread);
Налаживаем связь между потоком и обработчиком. Ключ на старт!
// При запуске потока запускаем выполнение метода Worker::process() connect(thread, Worker::process); // При излучении сигнала finished получаем флаг успешности и выводим в консоль соответствующее сообщение connect(worker, if(state) std::cout ); // Также, по сигналу finished отправляем команду на завершение потока connect(worker, QThread::quit); // А потом удаляем экземпляр обработчика connect(worker, QObject::deleteLater); // И наконец, когда закончит работу поток, удаляем и его connect(thread, QObject::deleteLater);
3..2..1.. Поехали! Запускаем выполнение потока
thread->start();
Реализация метода makeThread() завершена. Для проверки выполните следующий код и наблюдайте за стандартным выводом приложения:
Controller ctrl; ctrl.makeThread();
3. Переопределение метода run() класса QThread
Второй способ заключается в наследовании класса QThread и переопределении метода run(). Однако, этот метод нарушает принципы SOLID в подавляющем большинстве случаев, поэтому пойдем окольными путями
Вместо наследования создадим свой класс и передадим один из его методов на выполнение в отдельный поток. В качестве нагрузки используем уже знакомый класс HeavyWork, а выполнять работу будем в классе AnotherController
class AnotherController : public QObject < Q_OBJECT public: void makeThread(); >;
, где метод makeThread() реализуем следующим образом:
1. Создаем экземпляр класса HeavyWork
HeavyWork* work = new HeavyWork();
2. Создаем поток через статический метод QThread::create() принимающий Function в качестве параметра. Function — это адаптер функциональных объектов. Создать адаптер можно с помощью функции std::bind из стандартной библиотеки шаблонов (STL).
Этот адаптер будет запущен при запуске потока. Синтаксис следующий:
QThread* thread = QThread::create(std::bind(
Первым аргументом будет указатель на метод doWork класса HeavyWork, а далее передаем контекст — указатель на конкретный класс, метод которого будет запущен. Нечто похожее проделывали в методе connnect для сигналов и слотов.
Далее через запятую указываются аргументы, если они нужны, которые будут переданы в метод doWork, но в нашем случае у метода doWork аргументы отсутствуют.
3. Налаживаем связь
connect(thread, QObject::deleteLater); connect(thread, Qobject::deleteLater);
В этом случае сигналов стало меньше, в виду того, что некоторые из них принадлежали объекту Worker, который теперь не используется, однако, ничего не мешает добавить сигналы в класс HeavyWork и связаться с ними.
4. И наконец запускаем выполнение потока.
thread->start();
Метод makeThread() реализован. Запуск программы аналогичен предыдущему случаю
AnotherController anCtrl; anCtrl.makeThread();
Результат выполнения также аналогичен первому способу. В вашем распоряжении теперь два способа для запуска потока и мы можем обсудить их достоинства и недостатки.
4. Достоинства и недостатки
- Второй способ требует меньшего количества строк кода, и на один объект меньше. Он проще в реализации, но позволяет выполнять лишь один метод.
- Поскольку только один метод находится в другом потоке в первом способе, то остальные методы могут быть использованы для управления тяжелым объектом из других потоков. Этот факт может выступать как достоинством, так и недостатком этого метода.
- Например, при использовании семафоров или мьютексов во втором способе происходит блокировка всего потока, но т. к. в этом случае в отдельном потоке живет лишь один метод, то остальные могут быть вызваны в других потоках для модификации состояния объекта.
- С другой стороны этот способ инкапсулирует мьютексы и другие управляющие элементы внутри одного объекта, позволяя управлять ими только через методы. В обоих случаях (3 и 4) программисту следует уделить много внимания такой структуре, т. к. в некоторых случаях можно заморозить другой поток, в котором вызывается блокирующий метод тяжелого класса.
- Первый способ создает, выполняет и уничтожает тяжелый объект внутри себя. Такой подход более потокобезопасен т. к. жизненный цикл объектов не зависит от внешних потоков. Также весь объект целиком замирает в ожидании при засыпании потока и управление может быть осуществлено только через внешние объекты, ссылки на которые переданы в тяжелый метод.
Исходя из выше написанного, можно заключить, что ни один из них не является панацеей и не даёт 100% гарантий, но «наломать дров» в первом способе чуть сложнее, чем во втором, если у вас большой и сложный объект. Однако, в случае когда у вас маленькая функция, можно смело использовать второй метод. Окончательное решение за выбор того или иного метода — за вами! Всего доброго!
Источник: zhitenev.ru
Краткий обзор кроссплатформенного фреймворка Qt
Qt — это кроссплатформенный фреймворк для разработки ПО на языке программирования C++(и не только). Также имеется и для Ruby — QtRuby, для Python — PyQt, PHP — PHP-Qt и других языков программирования. Разрабатывается компанией Trolltech с 1996 года.
С использованием этого фреймворка написано множество популярных программ: 2ГИС для Android, Kaspersky Internet Security, Virtual Box, Skype, VLC Media Player, Opera и другие. KDE — это одно из окружений рабочего стола со множеством программ для Linux написано с использованием фреймворка Qt.
Qt полностью объектно-ориентированная, кросс-платформенная. Дает возможность разрабатывать платформо-независимое ПО, написанный код можно компилировать для Linux, Windows, Mac OS X и других операционных систем. Включает в себя множество классов для работы с сетью, базами данных, классы-контейнеры, а также для создания графического интерфейса и множество других(чуть ниже).
Qt использует MOC (Meta Object Compiler) для предварительной компиляции программ. Исходный текст программы обрабатывается MOC, который ищет в классах программы макрос Q_OBJECT и переводит исходный код в мета-объектный код, после чего мета-объектный код компилируется компилятором C++. MOC расширяет функциональность фреймворка, благодаря ему добавляются такие понятия, как слоты и сигналы.
В Qt имеется огромный набор виджетов (Widget), таких как: кнопки, прогресс бары, переключатели, checkbox, и другие — они обеспечивают стандартную функциональность GUI (графический интерфейс пользователя). Позволяет использовать весь функционал пользовательского интерфейса — меню, контекстные меню, draghttps://nicknixer.ru/programmirovanie/kratkij-obzor-krossplatformennogo-frejmvorka-qt/» target=»_blank»]nicknixer.ru[/mask_link]