Как создать приложение qt widgets
В сложных проектах может быть недостаточно наличия статических виджетов в интерфейсе программы, поскольку поступающая информация может изменяться ежесекундно. Следовательно поднимается вопрос о динамическом создании виджетов, например кнопок в компоновщике Qt.
В данном уроке описывается процесс динамического создания кнопок QPushButton, приёма сигналов от этих кнопок, а также последующее удаление этих кнопок из компоновщика Qt.
Программный код был написан в QtCreator 3.3.1 на основе Qt 5.4.1.
Структура проекта
Описание структуры проекта:
- DynamicButtons.pro - профайл;
- mainwindow.h - заголовочный файл основного окна приложения;
- mainwindow.cpp - исходный код окна;
- main.cpp - основной исходный файл, с которого стартует приложение;
- mainwindow.ui - формочка основного окна приложения;
- qdynamicbutton.h - заголовочный файл класса обертки, который упрощает процесс работы с динамическими объектами в данном уроке;
- qdynamicbutton.cpp - исходный файл класса обертки, который упрощает процесс работы с динамическими объектами в данном уроке.
mainwindow.ui
В данном уроке нам понадобится два слоя layout . В одном будут находиться все динамически создаваемые кнопки, а во втором слое будут находиться кнопки, которые будут отвечать за процесс создания и удаления динамических кнопок, а также поле lineEdit для отображения номера создаваемых кнопок.
Непосредственная работа будет осуществляться со следующими объектами формы окна приложения:
- addButton - кнопка для добавления динамических кнопок;
- deleteButton - кнопка для удаления динамических кнопок;
- verticalLayout - слой для добавления динамических кнопок с вертикальной компоновкой;
- lineEdit - поле для отображения номеров созданных кнопок.
qdynamicbutton.h
Заголовочный файл класса обёртки, который наследуется от класса QPushButton. В Данном классе объявляется статическая переменная, которая будет общей для всех объектов класса и будет являться счетчиков всех динамических кнопок, которые будут создаваться в данном приложении. Это необходимо для адекватного присвоения номеров каждой кнопки.
qdynamicbutton.cpp
В файле исходного кода класса-обёртки производится инициализация кнопки в её конструкторе, инициализация статической переменной, а также находится метод для возврата номера динамической кнопки.
mainwindow.h
В заголовочном файле требуется добавить только СЛОТы для обработки нажатий управляющих кнопок и СЛОТ для получения номера нажатой динамической кнопки.
В результате у Вас должно получиться приложение, которое осуществляет динамическое создание и удаление кнопок. Работа приложения показана в видео приведённом ниже.
Из-за того, что все возможности базы данных не реализуешь, да они и могут появляться каждый день новые, нужно было добавить в графический интерфейс консоль. На основе какого виджета в Qt ее имитировать, и как, и хочу вам рассказать.
От беспредела к тотальному контролю
Для базового виджета консоли я выбрал QPlainTextEdit. Во-первых, он включает в себя расширенные возможности редактирования текста, которые нам могут понадобиться, а во-вторых, он позволяет добавлять форматирование: подсветка разных элементов цветом нам бы не помешала.
Итак, создаем потомка QPlainTextEdit.
Несмотря на то, что QPlainTextEdit – это упрощенная версия QTextEdit, он разрешает пользователю делать черезчур большое количество действий, непозволительное для приличной консоли.
Поэтому первое, что мы сделаем, — это ограничим все, что только можно. Перейдем от полного беспредела к тотальному контролю.
Для этого переопределим встроенные слоты, получающие нажатия клавиш и клики мышки:
После этих строк пользователь не сможет ни ввести символ в поле виджета, ни выделить кусок текста, ни удалить строку – полная блокировка.
Этап либерализации
Теперь пойдем от тотального запрета к разумной демократии, попутно разрешая все, что понадобится.
Первое, что сделаем – это определим строку приглашения (prompt):
И выведем строку приглашения в консоль:
Нужно, чтобы при клике мышкой нельзя было переставить курсор, но можно было сделать консоль активной:
При вводе обычных букв, цифр и других полезных символов, они должны добавляться в строку команды:
Символы можно стирать клавишей Backspace, но не все, а только до определенного момента – чтобы строка приглашения не дай бог не затерлась:
Определим реакцию виджета на ввод команды (при нажатии клавиши Enter):
При вводе команды мы вырезаем кусок текста от строки приглашения до конца текстового блока и испускаем сигнал, к которому можно будет присоединить слот:
Так же на время обработки команды приложением, устанавливаем флажок блокировки текстового поля.
Приложение – родитель виджета обработает команду и передаст консоли результат выполнения, тем самым разблокируя ее:
История команд
Хотелось бы, чтобы история всех вводимых команд сохранялась и при нажатии клавиш вверх/вниз можно было бы по ней перемещаться:
Делаем красиво: раскраска консоли
Для этого в конструкторе виджета определим общую гамму цвета для консоли – фон черный, буквы вводимой команды – зеленые:
При выводе строки приглашения делаем шрифт зеленого цвета:
А при выводе результата выполнения команды делаем шрифт белого цвета:
Все вниз!
Также хотелось бы, чтобы когда пользователь вводит команду, скроллбар текстового поля консоли проматывался до самого низа:
Результат
В результате получилась веселая, красивая и удобная консолька. У меня это заняло всего 120 строк кода. Конечно, есть еще много вещей, которые можно было бы сделать, но основная функциональность реализована.
Ссылки
Там можно посмотреть класс виджета Console и скачать скомпилированный бинарник приложения для Windows, нажав кнопку «Downloads».
На этом уроке мы рассмотрим следующие виджеты в Qt5:
Виджет QLabel
Виджет QLabel используется для отображения текста или изображения. При этом стоит отметить, что у него не предусмотрено взаимодействие с пользователем. В следующем примере мы задействуем данный виджет для отображения в окне текстов песен.
Заголовочный файл — label.h:
Файл реализации — label.cpp:
QString lyrics = "Who doesn't long for someone to hold\n\Создаем виджет метки и устанавливаем для него определенный шрифт:
Основной файл программы — main.cpp:
Результат выполнения программы:
Виджет QSlider
Виджет QSlider представляет собой вертикальный или горизонтальный ползунок (слайдер). Он позволяет пользователю перемещать маркер ползунка вдоль горизонтальной или вертикальной линии и переводит положение ползунка в целочисленное значение в пределах допустимого диапазона.
В следующем примере у нас есть два виджета: слайдер и метка. Ползунок будет управлять числом, отображаемым в метке.
Заголовочный файл — slider.h:
Файл реализации — slider.cpp:
static_cast < void ( QLabel :: * ) ( int ) > ( &QLabel :: setNum ) ) ;Создаем горизонтальный QSlider :
Далее подключаем сигнал valueChanged() к встроенному в метку слоту setNum(). Поскольку метод setNum() перегружен, то мы используем оператор static_cast для выбора корректного метода:
static_cast < void ( QLabel :: * ) ( int ) > ( &QLabel :: setNum ) ) ;Основной файл программы — main.cpp:
Результат выполнения программы:
Виджет QComboBox
QComboBox — это виджет выбора, который отображает текущий элемент и может отображать выпадающий список выбираемых элементов. Список при этом может быть редактируемым, позволяя пользователю изменять каждый элемент в данном списке.
В следующем примере выбранный элемент из QComboBox будет отображаться в метке.
Заголовочный файл — combobox.h:
Файл реализации — combobox.cpp:
QStringList distros = < "Arch" , "Xubuntu" , "Redhat" , "Debian" , connect ( combo , static_cast < void ( QComboBox :: * ) ( const QString & ) > ( &QComboBox :: activated ) ,В QStringList хранятся данные QComboBox , а именно список названий дистрибутивов Linux:
QStringList distros = < "Arch" , "Xubuntu" , "Redhat" , "Debian" ,Создаем QComboBox , а затем с помощью метода addItems() добавляем в него элементы:
Сигнал activated() нашего QComboBox подключается к слоту setText() метки. Поскольку сигнал перегружен, то мы делаем статическое преобразование данных при помощи оператора static_cast:
connect ( combo , static_cast < void ( QComboBox :: * ) ( const QString & ) > ( &QComboBox :: activated ) ,Основной файл программы — main.cpp:
Результат выполнения программы:
Виджет QSpinBox
QSpinBox — это виджет, который используется для обработки целых чисел и дискретных наборов значений. Данный виджет позволяет пользователю указать нужное значение либо вручную, либо кликая мышкой по кнопкам вверх/вниз, либо нажимая клавиши клавиатуры вверх/вниз для увеличения/уменьшения значения, отображаемого в текущий момент.
В следующей программе с помощью виджета QSpinBox мы можем выбирать число от 0 до 99. Выбранное в текущий момент значение отображается в метке.
Заголовочный файл — spinbox.h:
Файл реализации — spinbox.cpp:
connect ( spinbox , static_cast < void ( QSpinBox :: * ) ( int ) > ( &QSpinBox :: valueChanged ) , lbl , static_cast < void ( QLabel :: * ) ( int ) > ( &QLabel :: setNum ) ) ;Нам нужно выполнить конвертацию с помощью оператора static_cast дважды, потому что и сигнал, и слот перегружены:
connect ( spinbox , static_cast < void ( QSpinBox :: * ) ( int ) > ( &QSpinBox :: valueChanged ) , lbl , static_cast < void ( QLabel :: * ) ( int ) > ( &QLabel :: setNum ) ) ;Основной файл программы — main.cpp:
Результат выполнения программы:
Виджет QLineEdit
Виджет QLineEdit представляет собой редактор однострочного текста. Редактор строки позволяет пользователю вводить одну строку обычного текста и при этом использовать такие функции редактирования, как: отмена, повтор, вырезание, вставка, а также перетаскивание с помощью механизма drag-and-drop.
В следующем примере мы выведем три метки и три строки для редактирования, которые скомпонованы с помощью менеджера компоновки QGridLayout.
Заголовочный файл — ledit.h:
Файл реализации — ledit.cpp:
name -> setAlignment ( Qt :: AlignRight | Qt :: AlignVCenter ) ; age -> setAlignment ( Qt :: AlignRight | Qt :: AlignVCenter ) ; occupation -> setAlignment ( Qt :: AlignRight | Qt :: AlignVCenter ) ;Основной файл программы — main.cpp:
Результат выполнения программы:
Строка состояния
Строка состояния (англ. «statusbar») — это панель, которая используется для отображения информации о состоянии приложения. Виджет Statusbar является частью виджета QMainWindow .
Заголовочный файл — statusbar.h:
Файл реализации — statusbar.cpp:
hbox -> addWidget ( okBtn , 0 , Qt :: AlignLeft | Qt :: AlignTop ) ; hbox -> addWidget ( aplBtn , 1 , Qt :: AlignLeft | Qt :: AlignTop ) ; connect ( okBtn , &QPushButton :: clicked , this , &Statusbar :: OnOkPressed ) ; connect ( aplBtn , &QPushButton :: clicked , this , &Statusbar :: OnApplyPressed ) ; statusBar ( ) -> showMessage ( "Apply button pressed" , 2000 ) ;Виджет QFrame помещается в центральную область виджета QMainWindow . Центральную область может занимать только один виджет:
Мы создаем два виджета QPushButton и компонуем их вдоль горизонтальной линии. Родительским элементом кнопок является виджет frame :
hbox -> addWidget ( okBtn , 0 , Qt :: AlignLeft | Qt :: AlignTop ) ; hbox -> addWidget ( aplBtn , 1 , Qt :: AlignLeft | Qt :: AlignTop ) ;Для отображения строки состояния мы вызываем метод statusBar() виджета QMainWindow :
Основной файл программы — main.cpp:
Результат выполнения программы:
Заключение
Как вы уже могли заметить, виджеты являются простым, но в то же время довольно мощным инструментом построения графической части приложений, созданных при помощи Qt5. На следующем уроке мы продолжим тему виджетов.
(34 оценок, среднее: 4,74 из 5)Урок №9. Слоты, Сигналы и События в Qt5
Комментариев: 14
Не могу понять, что есть userData = QVariant().
Возможно ли хранит нужные пользовательские данные в элементе меню QComboBox?
Добавляю AddItem func(text string, userData core.QVariant_ITF), все отображается.
Но вот незадача: нужно при выборе элемента меню получать ID (НЕ ИНДЕКС) этого элемента, который я хочу хранить в userData.
Ситуация следующая: есть список городов из openweather:
В QComboBox я добавляю список из городов и стран : Novyi Svit UA.
При сигнале activated на Novyi Svit UA нужно получать 8224454.
Добрый день.
Подскажите для чего делать преобразование:
если можно сделать так:
connect ( combo , & QComboBox :: textActivated , lbl , & QLabel :: setText ) ; Дмитрий Бушуев :"Сигнал activated() нашего QComboBox подключается к слоту setText() метки. Поскольку сигнал перегружен, то мы делаем статическое преобразование данных при помощи оператора static_cast:
connect(combo, static_cast<void(QComboBox::*)(const QString &)>(&QComboBox::activated),
label, &QLabel::setText);
"
Вам не нравится замена устаревшего в Вашем примере &QComboBox::activated на textActivated это Вас смутило ? Так QT указывает, что Ваш пример устарел и рекомендует его поменять на textActivated. Но по существу на вопрос Вы так и не ответили, ответьте пожалуйста на вопрос.
Дмитрий Бушуев :Сигнал QComboBox::activated является перегруженным и имеет прототип activated(int index), т.е. работает с числами. Мы же хотим потребовать от него, чтобы он работал со строками, т.е. как activated(const QString &). Для этого компилятору явно даём понять, что нужно вызывать именно функцию activated(const QString &), выполняя приведение функции с прототипом activated(int index) к прототипу activated(const QString &) с помощью оператора static_cast:
static_cast<void(QComboBox::*)(const QString &)>(&QComboBox::activated)
Ключевых момента здесь два, а именно:
1. Да, действительно, на данный момент сигнал QComboBox::activated помечен как "устаревший" (deprecated) и что вместо него рекомендуется использовать QComboBox::textActivated. Но это не значит, что надо бросать всё и вот прям здесь и сейчас переписывать код с QComboBox::activated на QComboBox::textActivated.
Вообще говоря, метка "deprecated" означает, что помечаемый ею объект (функция, класс, переменная, что угодно) из последующих версий компилятора может быть изъят. Но сейчас то он есть! Более того, в данный момент я вполне успешно откомпилировал и запустил проект с примером про QComboBox на своей машине (Qt 5.15.2, MSVC 2019 x64; Qt Creator 4.14.2).
2. Рекомендуемая замена (которую вы использовали) в лице QComboBox::textActivated не является перегруженной, "из коробки" имеет нужный нам прототип textActivated(const QString &text) и не требует выполнение приведения типа через оператор static_cast.
Юрий :Рис. 1. Стартовое окно Qt Creator
Рис. 2. Выбор типа проекта
Рис. 3. Окно выбора размещения проекта
Рис. 4. Параметры комплекта
Нажмите ОК и Далее. В следующем окне необходимо определиться с названием класса и выбрать базовый класс (можно всё оставить как есть, по умолчанию).Рис. 5. Окно выбора базового класса
В следующем окне (Рис. 6) можно добавить контроль версий и увидеть какие файлы будут добавлены в проект:Рис. 6. Итоговое окно создания проекта
Рис. 7. Окно редактора форм
Элемент графического интерфейса Label предназначен для создание надписей на форме Обратите внимание, что окно будет оформлено в системные цвета. Если вы используете KDE (а эта среда основана на Qt), то будет использована текущая палитра Plasma, которая наследуется виджетами Qt.В левой боковой панели (внизу) нажмите кнопку Собрать проект (или Ctrl+B), а затем Запустить проект (или Ctrl+R). Появится окно вашего первого приложения:
Применение таблицы стилей для элементов
Для изменения внешнего вида элементов можно использовать таблицу стилей. Изменить (или создать) таблицу стилей можно в свойстве styleSheet . Найдите это свойство в инспекторе объектов. Или выполните: над label ЛКМ > Изменить StyleSheet (таблицу стилей). В окне Правка стилей > Добавить шрифт. Выберите какой-нибудь декоративный шрифт установленный в вашей системе. В окне мини-редактора появится правило каскадной таблицы стилей. Добавьте цвет текста:
Или нажмите на кнопку Добавить цвет > background-color и определите цвет фона для окна. Возможный результат на Рис. 10:
Задания для самостоятельной работы
Оцените материал
(3 оценок, среднее: 5,00 из 5)
Загрузка.
Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.
Читайте также: