Как сделать кнопку неактивной qt

Обновлено: 05.07.2024

БлогNot. QT: "одноразовые" кнопки

QT: "одноразовые" кнопки

Была на днях проблемка у человека, вот к ней пример. Требовалось иметь в программе набор кнопок, нажатия которых будут "одноразовыми", то есть, кнопка после первого нажатия выполняет некий код и деактивируется. При этом, писать кучу однотипных обработчиков нажатия кнопок не хочется, а хочется иметь один слот-обработчик, который будет как-то различать кнопки между собой (какая именно из них была нажата). Разумеется, вместо кнопок можно и с другими компонентами обращаться по аналогии.

Нет ничего легче. С помощью QT Creator создадим класс-потомок QWidget : меню Файл - Новый файл или проект - слева выбрать "Приложения", справа "Приложение Qt Widgets", нажать кнопку "Выбрать", ввести какое нужно Название, например, OneClick , нажать кнопку "Далее" еще 2 раза, выбрать базовый класс = QWidget , указать нужное Имя класса, например, Widget . Форму создавать не нужно, мы её создадим программно, так что отключаем эту галочку. Снова жмём кнопку "Далее", потом "Завершить".

В заголовочном файле widget.h предусмотрим метод createButton для программного создания одной кнопки с нужной надписью и слот slotButtonClicked , который будет обрабатывать нажатия всех кнопок, вот полный код файла:

Рад снова всех приветствовать! Как известно, спрос рождает предложение, поэтому я решил опубликовать цикл статей, посвященных различным аспектам QML 👍 Пройдемся более менее масштабно, начиная с основных интерактивных элементов для взаимодействия с пользователем, таких как Button , CheckBox , ComboBox и т. д…. И не оставим в стороне также более узконаправленные нюансы. При этом среди вопросов по этой тематике добрую половину представляют из себя вопросы по кастомизации стиля и внешнего вида элементов. Соответственно, этому уделим отдельное внимание, конечно же, все будет сопровождаться конкретными практическими примерами.

Не знал, с чего именно начать, но по факту последовательность тут особой роли не играет, так что без веской на то причины первым героем данного цикла будет тип Button . И в качестве отправной точки стабильно будем использовать пустой Qt Quick проект:

Qt Quick project.

В итоге имеем проект с двумя файлами с дефолтным содержимым, main.cpp:

Для использования Button сразу импортируем:

QML Button. Создание.

Итак, пустое приложение дает нам в результате запуска пустое же окно, и это прекрасно, ничего лишнего. Сегодня разбираем исключительно кнопку, поэтому создадим ее прямо в самом центре окна, сделав последнее чуть поменьше 👍:

Как и для практически любого компонента QML непосредственно добавление осуществляется элементарно, в чем мы и убедились. Вид на данный момент Button имеет дефолтный, ничем не примечательный, кастомизацией займемся чуть позже. Но прежде рассмотрим кратко функционал…

QML Button. События.

Итак, кнопка создана для того, чтобы ее нажимали. Поэтому разберемся, как обработать данное действие пользователя. И все также максимально просто, при помощи обработчика — onClicked :

Здесь мы по нажатию выводим строку в консоль. Пример настолько прост, что просто вгоняет в краску, поэтому минимально, но усложним. Добавим под кнопку текст, в который при нажатии будем выводить количество кликов по кнопке:

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

  • onCanceled
  • onClicked
  • onDoubleClicked
  • onPressAndHold
  • onPressed
  • onReleased
  • onToggled

Добавим еще одну текстовую строку для вывода последней произошедшей с кнопкой активности, а также пару обработчиков для наглядности:

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

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

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

QML Button. Стили. Кастомизация.

Давайте изначально систематизируем — у кнопки есть два объекта для настройки стиля — непосредственно сама прямоугольная область и текст, заключенный внутри нее. Поэтому QML предоставляет нам два соответствующих свойства:

Лучше всего разобраться можно на конкретных примерах, к ним и переходим. Для начала сделаем минимально необходимые вещи, а затем будем постепенно добавлять:

Полезные ссылки — Rectangle, Text — и результат:

Увеличим размер кнопки:

Проблема налицо, разместим текст по центру и сразу же немного увеличим шрифт:

Уважающая себя кнопка должна иметь отклик в виде изменения оформления при действиях пользователя — наведении курсора, нажатии кнопки и т. д. Поэтому добавим цвета:

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

Ну и, пожалуй, на этом сегодня и остановимся, до встречи🤝 Если возникли какие-либо вопросы или проблемы, буду рад помочь с решением, пишите в комментарии, либо на форум.

Оригинал: Developing Apps on Qt, Part 4
Автор: Manoj Kumar
Дата публикации: 3 мая 2012 г.
Перевод: А.Панин
Дата публикации перевода: 8 ноября 2012 г.

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

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

Одним из самых простых, но очень важных виджетов является кнопка. Например, на Рисунке 1 показано диалоговое окно с двумя кнопками "Cancel" и "Close Tabs", которое отображается при попытке закрытия окна браузера Firefox с несколькими открытыми вкладками. Без кнопок графические интерфейсы становятся бесполезными. Все классы виджетов-кнопок наследуются от класса QAbstractButton , который представляет четыре сигнала - clicked() , pressed() , released() и toggled() , и пять состояний - isChecked() , isEnabled() , isDown() , setCheckable() и setAutoRepeat() . Мы затронем их в примере исходного кода позднее. Некоторые классы, наследуемые от QabstractButton : QPushButton , QRadioButton и QCheckBox .

Кнопки PushButton (или просто кнопки)


Рисунок 1: Кнопки PushButton (или просто кнопки)

Давайте начнем рассмотрение виджетов с класса QPushButton . Этот виджет используется для того, чтобы позволить пользователю инициировать какое-либо действие, примерами являются кнопки "OK", "Отмена", "Применить", "Сохранить", и.т.д. Виджет QPushButton генерирует сигналы clicked() , pressed() и released() . Мы будем использовать механизм сигналов и слотов, описанный в предыдущей статье, для демонстрации принципа использования кнопок.

Создайте приложение с графическим интерфейсом ("GUI приложение Qt") и перетащите виджет pushButton на окно диалога. Вы можете изменить имя виджета со стандартного pushButton при помощи клика правой кнопкой мыши, выбора пункта "Изменить objectName" ("Change objectName") во всплывающем меню и ввода нового имени в появившемся окне. Таким же образом вы можете переименовать диалоговое окно и другие классы.

Примечание: исходный код программ из данной статьи доступен в формате zip-архива по ссылке .

Перед тем, как рассматривать другие классы, относящиеся к графическому интерфейсу, нам необходимо упомянуть важный класс QMessageBox , который очень часто используется. Например, при закрытии несохраненного документа в приложениях на Qt появляется всплывающее окно, использующее этот класс, с вопросом: хотите ли вы сохранить документ или закрыть без сохранения. Главным образом этот виджет используется для предупреждения пользователя; он может показывать текст и иконки, пользователю даже может быть предоставлена возможность ввести какой-либо текст.

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

Радио-кнопки (Radio buttons)

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

Вы можете выполнять действия в зависимости от значения переменной типа bool . Радио-кнопки используют "встроенный" виджет строки, поэтому вам не нужно использовать дополнительных виджетов для вывода текста рядом с кнопками.

Иногда необходимо выбрать сразу несколько вариантов из группы возможных - напрмер, пользователь выбирает три цвета из пяти. В этом случае радио-кнопки не подойдут и придется использовать виджет checkBox, который поддерживает два состояния и позволяет отмечать или не отмечать выбранные варианты. И снова сигнал clicked() генерируется при нажатии на кнопку, а переменная типа bool передается слоту. Код примера можно скачать по ссылке в примечании. Рисунки со 2 по 4 являются скриншотами получившегося приложения.

Кнопка выбора (CheckBox)


Рисунок 2: Кнопка выбора (CheckBox)

Радио-кнопки (RadioButtons)


Рисунок 3: Радио-кнопки (RadioButtons)

Помимо этих кнопок, в приложениях с графическим интерфейсом необходимы виджеты списков. Рассмотрим два виджета - раскрывающийся список (combo box) и список (list).

Раскрывающийся список предоставляет ниспадающее меню и показывает только выделенный элемент списка - в этом состоит достоинство виджета, поскольку он занимает минимум полезного пространства окна. В Qt этот виджет предоставляется классом QcomboBox . Элементы списка могут добавляться и удаляться также и во время исполнения программы. Сигнал генерируется в том случае, если пользователь меняет выбранный элемент. Если вы хотите предоставить пользователю возможность видеть сразу весь список, используйте класс QListWidget . Помотрите на Рисунок 5. Раскрывающийся список показывает только один элемент, а обычный список, представленный классом QListWidget - все элементы. Следующий код показывает, как добавлять элементы в эти списки.

Раскрывающийся список (ComboBox) и список (ListWidget)


Рисунок 5: Раскрывающийся список (ComboBox) и список (ListWidget)

Простой пример

А начнем мы с простого примера, который отображает на экране стандартное окно:

Результат выполнения программы:



Всплывающая подсказка

Всплывающая подсказка — это небольшой всплывающий прямоугольник с некоторым текстом, который появляется, когда вы наводите курсор на какой-нибудь элемент в приложении. В нижеследующем примере мы создадим всплывающую подсказку для нашего основного окна:

Результат выполнения программы:



Иконка для приложения

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

Для отображения иконки мы используем метод setWindowIcon() и класс QIcon. Иконка представляет собой небольшой .jpg-файл, расположенный в текущем рабочем каталоге:

Результат выполнения программы:



Курсор

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

frame3 -> setCursor ( Qt :: PointingHandCursor ) ; // задаем тип курсора PointingHandCursor для фрейма

Результат выполнения программы:



Кнопка

В следующем примере мы добавим на нашу форму самую обычную кнопку. Нажатие на кнопку приведет к закрытию приложения. И здесь же впервые будут использованы понятия сигналов и слотов:

quitBtn -> setGeometry ( 50 , 40 , 75 , 30 ) ; // изменяем размеры кнопки в пикселях и помещаем на форму окна

При нажатии на кнопку, генерируется сигнал clicked . Слот — это метод, который реагирует на сигнал. В нашем случае это будет слот quit основного объекта приложения. QApp — это глобальный указатель на объект приложения. Он определен в заголовочном файле QApplication.

Результат выполнения программы:



Взаимодействие виджетов

Мы заканчиваем этот урок примером, который демонстрирует возможность виджетов взаимодействовать друг с другом. Код данного примера разделен на три файла.

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

Заголовочный файл — plusminus.h:

Q_OBJECT // этот макрос должен включаться в классы, которые объявляют свои собственные сигналы и слоты

У нас есть две кнопки и виджет lbl . С помощью кнопок мы увеличиваем или уменьшаем число, отображаемое в lbl .

Файл реализации — plusminus.cpp:

А здесь происходит соединение сигналов clicked с соответствующими слотами:

В методе OnPlus() мы определяем текущее значение в lbl . Виджет lbl отображает строковое значение, поэтому сначала его нужно преобразовать в целое число. Затем мы это число увеличиваем, конвертируем получившееся число снова в строковое значение и устанавливаем новый текст для label :

lbl -> setText ( QString :: number ( val ) ) ; // конвертируем обратно в Qstring и устанавливаем новый текст для label

Метод OnMinus() отличается от метода OnPlus() только тем, что в OnMinus() значение не инкрементируется, а декрементируется (уменьшается на единицу).

А это уже наш основной файл — main.cpp:

Результат выполнения программы:



Заключение

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

Урок №5. Работа с файлами и каталогами в Qt5

Комментариев: 29

Насчёт добавления иконки — приведённый код не захотел работать.
Делал в Qt creator 4.14.2 (Qt 5.15.2)

Как я его заставил работать:
1. Положил иконку в папку с проектом. Я использовал файл с расширением *.ico
2. В QT-Creator ПКМ по проекту — "добавить новый…" — раздел в шаблонах "Qt" — "Файл ресурсов Qt" — выбрать — пишем имя_файла_ресурсов (например res) — Далее — завершить
3. По умолчанию файл ресурсов должен открыться в редакторе. Если не открылся: ПКМ по файлу ресурсов — "открыть в редакторе"
4. "Добавить префикс" — поменять имя. Я использовал "/ico". Имя запомнить. В дальнейшем это важно.
5. Выделяем появившуюся папку с префиксом "/ico" — "Добавить файлы" — выбираем файл с иконкой
6. В коде меняем адрес файла по следующему образцу

Если не получится — проверяйте наличие в файле проекта имя_проекта.pro наличие строчки RESOURCES += \имя_файла_ресурсов.qrc

Здравствуйте, прямоугольные кнопки с текстом — это хорошо, но, скажите, пожалуйста, есть ли возможность вставить картинку и сделать её кнопкой? (Т.е. чтобы при нажатии на картинку, например, закрывалась программа?)

Да. У картинки есть конструктор, принимающий Pixmap. Потом соединяем QPushButton::clicked и QApplication::quit и всё

Подскажите пожалуйста, почему в примере про взаимодействие виджетов в классе PlusMinus в списке private членов указан только один label, а две кнопки — не указаны, и создаются в конструкторе?

Потому что виджет lbl мы используем в методах OnPlus/OnMinus, т.е. нам нужно иметь доступ к этому виджету. В то время как кнопки нам нужно только создать

Расскажите пожалуйста о методе move().

Дмитрий Бушуев :

Тут всё очень просто: метод move(300, 300) перемещает виджет (в нашем случае — окно) в позицию с координатами (300,300).

P.S.: Попробуйте поставить другие значения координат и посмотреть на результат 🙂

Добрый день!
Пытаюсь изучать с вашей помощью QT, за что Вам огромное спасибо!)
У меня возник такой вопрос) в программе есть такая штука как дизайнер, с помощью которой удобно создавать объекты на нашем окне приложения и сигналы со слотами)
Какие у этого способа минусы и каким способом лучше писать приложения?)

Дмитрий Бушуев :

И вам спасибо за вашу благодарность.
По поводу вопроса — лучше выбирать тот способ, которым вам удобнее пользоваться.
Плюсы Qt-дизайнера в том, что вы сразу можете видеть результат вашей работы. Как следствие — меньше головной боли, особенно если в приложении используются различные (в том числе вложенные) компоновки.
Минусы же его состоят в том, что, если вам нужно сделать что-то, чего нет в стандартном наборе компонентов, то добро пожаловать в написание кода "голыми руками" 🙂

Походу да — нужно выбирать что типа QT widget application.
Для меня тоже немного сложновато, некоторых неочевидных вещей нехватает. Плюс еще плаваю в самом C++

Как решили ситуацию?(У меня сейчас подобное происходит)

Дмитрий Бушуев :

Создайте проект типа "Приложение Qt Widgets"…

Дмитрий Бушуев :

Нужно создавать проект типа "Приложение Qt Widgets".

QT+=core gui widgets
CONFIG += c++11

Пишет, что С++ требует type specifier for all declarations.

Вообще я так посмотрел, без увернного знания С++ в QT делать нечего? Смотрю как баран на новые ворота на все жти квадраточия, наследования классов, т.п. Перывые пару уроков еще зашли, а дальше банальное "переписывание с доски"…эх…
Замкнутый круг, чтоб научиться прогать на С++ нужно уметь прогать на С++…

Дмитрий Бушуев :

Проверил у себя. Всё работает.

Добрый день. Подскажите пожалуйста в примере с курсорами в конструкторе класса Cursors задается стандартное значение указателя parent = 0. Можно ли туда заместо 0 передавать nullPtr?

Дмитрий Бушуев :

Немного не понял вопроса… Если вы имеете в виду — можно ли вместо parent = 0 использовать parent = nullPtr, то ответ — да, можно. Вообще говоря, в наших уроках с этим проблем нет, но вот в более серьезных программах предпочтительнее использовать вариант parent = nullPtr, т.к. из-за автоприведения типов в Си++, которое иногда (неочевидным образом) может приводить 0 или NULL (который заменяется на 0) к целому числу и вызывать косяки.

Насчёт первого примера — лучше бы воспользоваться QHBoxLayout, всё-таки он чуть быстрее, да и нужны в группировке таблицей тут нет… А вообще да, спасибо за труд.

Дмитрий Бушуев :

Т.е. в QT есть что-то типа garbage collector? А можно поподробнее, как он здесь работает?

Дмитрий Бушуев :

В Qt есть есть класс, который является базовым для всех других классов и объектов. Называется он — QObject. Когда вы создаете свой класс или объект при помощи прямого наследования (непосредственно от QObject) или косвенного (через цепочку промежуточных классов, которые были наследованы от QObject), то вам становится доступен механизм связи объектов, а именно: организация в т.н. иерархии (или деревья объектов). Чтобы его задействовать, нужно при создании объекта-потомка передавать в качестве параметра указатель на объект-предок. И тогда, при удалении родительского объекта, Qt автоматически удалит и всех связанных с ним потомков.

Пример для наглядности:

QObject* child3 = new QObject ( child1 ) ; //Можно и так сделать, т.е. назначить child1 родителем для child3

delete parent ; // Удаляем объект parent. При этом Qt автоматически удалит и все связанные с ним объекты-потомки: child1, child2, child3

Простите, вот я такой момент недопонял: в конструкторе классов создаются указатели с выделением памяти. Как потом очищается память? Если эти указатели были бы полями класса, инициализировались в конструкторе и в деструкторе delete`лись, я бы понял. А так получается утечка памяти, вроде как. Поясните этот момент, пожалуйста

Дмитрий Бушуев :

>>Как потом очищается память?
Обратите внимание на второй параметр ("this") в примере ниже:

Читайте также: