Опубликован: 07.03.2015 | Уровень: для всех | Доступ: свободно | ВУЗ: Компания ALT Linux
Лекция 14:

Собственные классы в Qt. Создание элементов графического интерфейса

14.5 Создание собственного элемента интерфейса. Создание свойств

QObject предоставляет механизм для объявления свойств. Свойства — это специальные общедоступные поля, через которые можно получить доступ к данным объекта. Свойства обычно имеют методы для установки и получения значения, вызываемые при чтении из свойства и записи данных. В Qt свойства выполняют специальную роль, ведь делают доступными для метаобъектной системы способы чтения и записи данных объектов, что часто используется в Qt для реализации различных механизмов (анимации, описание динамических пользовательских интерфейсов в QtQuick, и т. д.).

Определение свойства обычно состоит из макроса Q_PROPERTY, который описывает свойство и содержит описания:

  • метода для установки начального значения;
  • метода для получения значения;
  • метода для установки значения;
  • сигнала об изменении значения свойства;
  • дополнительных настроек.

Метод для установки значения принимает одно значение (того же типа, что и свойство) и возвращает void. Метод для получения значения возвращает значение свойства.

Обычно метод для получения значения называют так же как и свойство, а метод для установки значения ещё и имеет префикс "set". Метод для получения значения, который возвращает тип bool также обычно имеет префикс "is", например:

QStirng Text( ) const;
void setText ( const QString &Text);
bool isVisible ( ) const;
void setVisible ( bool isVisible );

Наличие отдельного метода для установки значения позволяет запрограммировать дополнительные действия, а также проверить допустимость значения, которое устанавливается. В свою очередь, отдельные методы для установки значения дают возможность косвенного использования уже существующих свойств. Изменение значения свойства возможно, как через прямое использование методов установки и получения значения свойства, так и используя средства метаобъектной системы Qt. Также есть возможность определения доступных свойств во время выполнения программы.

Мы рассмотрим определение свойств на примере создания собственного виджета-индикатора LedIndicator, который будет находиться в одном, включённом или выключенном, состоянии в зависимости от значения свойства.

Для начала, создадим оконный проект и добавим к нему класс LedIndicator, унаследованный от QWidget:

class LedIndicator : public QWidget
{
	Q_OBJECT
	Q_PROPERTY( QString TextREAD TextWRITE setText )
	Q_PROPERTY( bool turnedOn READ isTurnedOn WRITE setTurnedOn NOTIFY
	state toggled )
public :
	explicit LedIndicator ( QWidget * parent = 0 );
	QString Text( ) const;
	bool isTurnedOn ( ) const;
signals :
	void state toggled ( bool );
public slots :
	void setText ( const QString &);
	void setTurnedOn ( bool );
private :
	QString mText;
	bool mIsTurnedOn;
};

Мы определили два свойства: text типа QString для надписи, а также turnedOn типа bool для состояния индикатора. Специальные слова READ и WRITE в описании свойства обозначают названия методов для установления и изменения значения свойства. В описании второго свойства использовано слово NOTIFY для обозначения названия сигнала, который будет сообщать об изменении свойства. Добавим реализацию для класса:

#include <QPainter>
#include <QPaintEvent>
//Радиус индикатора
const int cLedRadius = 7;
//Отступ между индикатором и надписью
const int cLedSpacing = 5;
LedIndicator::LedIndicator ( QWidget * parent ) : QWidget ( parent ),
mIsTurnedOn ( false ) //Инициализируем начальным значением!
{
}
//Метод получения значения — свойство text
QString LedIndicator::Text( ) const
{
	return mText;
}
//Метод получения значения — свойство turnedOn
bool LedIndicator::isTurnedOn ( ) const
{
	return mIsTurnedOn;
}
//Метод установки значения — свойство text
void LedIndicator::setText ( const QString &pText )
{
	mText = pText;
}
//Метод установки значения — свойство turnedOn
void LedIndicator::setTurnedOn ( bool pIsTurnedOn )
{
	//Проверка уже установленного значения
	if ( isTurnedOn ( ) == pIsTurnedOn )
	{
		return;
	}
	mIsTurnedOn = pIsTurnedOn;
	//Выпускаем сигнал про изменение
	em it state toggled ( mIsTurnedOn );
	//Вызываем метод QWidget::update(), который добавляет в очередь событий QPaintEvent
	//для того чтобы перерисовать наш виджет в соответствии с установленным isTurnedOn()
	update ( );
}

Обратите внимание: в большинстве случаев при создании собственных слотов, которые получают и устанавливают значения, следует сравнивать переданное значение с текущим и запрещать выполнение тела слота, если переданное и текущее значения равны. Особенно за этим необходимо следить, если слот выдаёт сигнал об изменении значения. Об этом необходимо помнить, чтобы избежать бесконечной рекурсии и аварийного завершения программы в случае перекрёстного сигнально-слотового соединения между такими слотами. Именно такую проверку мы выполнили в методе setTurnedOn() перед отправкой сигнала об изменении и перерисовкой.

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

Сергей Радыгин
Сергей Радыгин

Символы кириллицы выводит некорректно. Как сделать чтобы выводился читабельный текст на русском языке?

Тип приложения - не Qt,

Qt Creator 4.5.0 основан на Qt 5.10.0. Win7.

 

Юрий Герко
Юрий Герко

Кому удалось собрать пример из раздела 13.2 Компоновка (Layouts)? Если создавать проект по изложенному алгоритму, автоматически не создается  файл mainwindow.cpp. Если создавать этот файл вручную и добавлять в проект, сборка не получается - компилятор сообщает об отсутствии класса MainWindow. Как правильно выполнить пример?