Урок №10. Виджеты в Qt5

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

  Обновл. 12 Фев 2021  | 

 16168

 ǀ   13 

Виджеты в Qt5 — это «строительные блоки» для создания пользовательского интерфейса. Визуальные объекты на форме, такие как кнопки, метки, поля, меню, раскрывающиеся списки и т.д. — всё это относится к виджетам.

На этом уроке мы рассмотрим следующие виджеты в Qt5:

   QLabel;

   QSlider;

   QComboBox;

   QSpinBox;

   QLineEdit;

   QMainWindow.

Виджет QLabel

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

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

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

Создаем виджет метки и устанавливаем для него определенный шрифт:

Основной файл программы — main.cpp:

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


Виджет QSlider


Виджет QSlider представляет собой вертикальный или горизонтальный ползунок (слайдер). Он позволяет пользователю перемещать маркер ползунка вдоль горизонтальной или вертикальной линии и переводит положение ползунка в целочисленное значение в пределах допустимого диапазона.

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

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

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

Создаем горизонтальный QSlider:

Далее подключаем сигнал valueChanged() к встроенному в метку слоту setNum(). Поскольку метод setNum() перегружен, то мы используем оператор static_cast для выбора корректного метода:

Основной файл программы — main.cpp:

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


Виджет QComboBox

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

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

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

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

В QStringList хранятся данные QComboBox, а именно список названий дистрибутивов Linux:

Создаем QComboBox, а затем с помощью метода addItems() добавляем в него элементы:

Сигнал activated() нашего QComboBox подключается к слоту setText() метки. Поскольку сигнал перегружен, то мы делаем статическое преобразование данных при помощи оператора static_cast:

Основной файл программы — main.cpp:

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


Виджет QSpinBox


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

В следующей программе с помощью виджета QSpinBox мы можем выбирать число от 0 до 99. Выбранное в текущий момент значение отображается в метке.

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

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

Нам нужно выполнить конвертацию с помощью оператора static_cast дважды, потому что и сигнал, и слот перегружены:

Основной файл программы — main.cpp:

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


Виджет QLineEdit

Виджет QLineEdit представляет собой редактор однострочного текста. Редактор строки позволяет пользователю вводить одну строку обычного текста и при этом использовать такие функции редактирования, как: отмена, повтор, вырезание, вставка, а также перетаскивание с помощью механизма drag-and-drop.

В следующем примере мы выведем три метки и три строки для редактирования, которые скомпонованы с помощью менеджера компоновки QGridLayout.

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

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

Основной файл программы — main.cpp:

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


Строка состояния


Строка состояния (англ. «statusbar») — это панель, которая используется для отображения информации о состоянии приложения. Виджет Statusbar является частью виджета QMainWindow.

В следующем примере у нас есть две кнопки и одна строка состояния. При нажатии на кнопку будет отображаться соответствующее сообщение.

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

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

Виджет QFrame помещается в центральную область виджета QMainWindow. Центральную область может занимать только один виджет:

Мы создаем два виджета QPushButton и компонуем их вдоль горизонтальной линии. Родительским элементом кнопок является виджет frame:

Для отображения строки состояния мы вызываем метод statusBar() виджета QMainWindow:

Метод showMessage() отображает сообщение в строке состояния. Последний параметр указывает количество миллисекунд, в течение которых сообщение отображается в строке состояния:

Основной файл программы — main.cpp:

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


Заключение

Как вы уже могли заметить, виджеты являются простым, но в то же время довольно мощным инструментом построения графической части приложений, созданных при помощи Qt5. На следующем уроке мы продолжим тему виджетов.


Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (28 оценок, среднее: 4,68 из 5)
Загрузка...

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

  1. Аватар Дмитрий:

    Добрый день.
    Подскажите для чего делать преобразование:

    если можно сделать так:

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

      >>Подскажите для чего делать преобразование […] QComboBox::textActivated […]

      Я не вижу в статье такого преобразования. А вот преобразование для QComboBox::activated — вижу. Выполняется оно вот для чего (опять-таки, цитата из статьи):

      "Сигнал activated() нашего QComboBox подключается к слоту setText() метки. Поскольку сигнал перегружен, то мы делаем статическое преобразование данных при помощи оператора static_cast:

      connect(combo, static_cast<void(QComboBox::*)(const QString &)>(&QComboBox::activated),
      label, &QLabel::setText);
      "

      1. Аватар Дмитрий:

        Вам не нравится замена устаревшего в Вашем примере &QComboBox::activated на textActivated это Вас смутило ? Так QT указывает, что Ваш пример устарел и рекомендует его поменять на textActivated. Но по существу на вопрос Вы так и не ответили, ответьте пожалуйста на вопрос.

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

          Сигнал 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)

          Чтобы было понятнее, советую прочитать:
          Урок №56. Оператор static_cast
          https://ravesli.com/urok-56-yavnoe-preobrazovanie-tipov-dannyh-operatory-casts/#toc-3

          Урок №104. Указатели на функции
          https://ravesli.com/urok-104-ukazateli-na-funktsii/
          ———————————————————————

          Теперь касаемо вашего тезиса о том, что я "по существу на вопрос так и не ответил".
          Давайте разберем ситуацию по-порядку. Вы берете ежа (функцию QComboBox::textActivated, о которой в статье вообще ни слова не упоминается), скрещиваете его с ужом (оператором static_cast) и спрашиваете (почему-то)меня "для чего вы их только что скрестили?". Ответ — вы скрестили их потому, что отошли от излагаемого в уроке материала, при это слабо понимая суть своих действий.

          Ключевых момента здесь два, а именно:
          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.

          Резюме:
          QComboBox::аctivated — перегруженный сигнал => требуется приведение через static_cast.
          QComboBox::textActivated — НЕ перегруженный сигнал => можно использовать напрямую
          Если уж решили лепить франкенштейна, отходя от материалов урока, то нужно явно про это указывать в своём вопросе.

        2. Юрий Юрий:

          Ваши комментарии удаляю я. На ваш вопрос ответили и все ваши последующие комментарии, которые не несут в себе ни сути, ни пользы — будут удалены.

  2. Аватар Сергей:

    Для примера "Виджет QComboBox", в файле combobox.cpp не прошла "Сборка -> Запустить". Строки

    пришлось заменить на

    и тогда все получилось.
    Спасибо за Ваши материалы!

  3. Аватар Алексей:

    Здравствуйте , подскажите пожалуйста по поводу перегруженных сигналов и слотов.
    Насколько я понял из документации сейчас предпочтительнее использовать QOverload?
    Так же не совсем понятно, почему мы приводим к указателю на функцию?
    Сигнал подключается к указателю на функцию и мы передаём указатель слоту?
    Запутался, помогите)

  4. Аватар Александр:

    Теперь, кажется, понял.
    Видим, что нам нужен SetNum >>>>> смотрим его в документации и видим, что есть 2 варианта in и double а нам нужен int.

    Просто сама запись static_cast как-то ускользает. Понятно, когда вот так:
    int i = 49;
    char ch = static_cast<char>(i);
    А тут преобразовать в указатель на функцию..

  5. Аватар Александр:

    Добрый день!
    В примере с виджетом QSlider
    в файле slider.cpp
    нехватает мозга понять последнюю строку несмотря на разъяснения.

    отправитель, сигнал,получатель, и вот последний параметр в коннект
    static_cast<void (QLabel::*)(int)>(&QLabel::setNum) что он делает?
    Преобразует в "void (QLabel::*)(int)" значение "(&QLabel::setNum)"
    Т.е. сам static_cast тут непонятен..

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

      Добрый!
      Смотрите, в самой статье уже идет подсказка:
      >"Поскольку метод setNum() перегружен, мы используем оператор static_cast для выбора корректного метода"

      …ага, если метод перегружен, значит есть и другие? Тогда идем в оф. доки по Qt, смотрим описание класса QLabel (https://doc.qt.io/qt-5/qlabel.html) и видим там две функции setNum():
      >void setNum(double num)
      >void setNum(int num)

      …теперь возвращаемся к строчке с "connect…". Как она работает? Да очень просто — она связывает источник сигнала — slider, сам сигнал — &QSlider::valueChanged, приемник сигнала — label и метод, которым этот сигнала будет обработан (т.е. слот) — функция setNum()…. эмм… а…. а у нас же их две, какая из них должна вызываться? Вот чтобы явно указать, что нам нужен вот такой вариант функции — setNum(int num) — мы и используем вариант приведения к функции void (QLabel::*)(int) через static_cast.

      Ведь что такое — void (QLabel::*)(int)? Это указатель на функцию-элемент класса QLabel, которая принимает в качестве аргумента одну переменную типа int и возвращает void. А такому прототипу соответствует только функция void QLabel::setNum(int num). Тем самым мы ясно дали понять, что хотим использовать в качестве слота (или по-простому — обработчика события) именно её, а не похожую функцию void setNum(double num).
      🙂

      1. Аватар Jane:

        Добрый день. Можете дать ссылку, где в С++ рассказывается про подобное применение static_cast<>? Хотелось бы подробнее вникнуть.

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

          Добрый.
          Я пользовался этой темой:
          https://ravesli.com/urok-56-yavnoe-preobrazovanie-tipov-dannyh-operatory-casts/#toc-3

      2. Аватар Jane:

        Спасибо за ссылку на static_cast<>

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *