Чтение онлайн

на главную - закладки

Жанры

QT 4: программирование GUI на С++

Саммерфилд Марк

Шрифт:

73 {

74 if (event->button == Qt::LeftButton) {

75 setImagePixel(event->pos, true);

76 } else if (event->button == Qt::RightButton) {

77 setImagePixel(event->pos, false);

78 }

79 }

Когда пользователь нажимает кнопку мышки, система генерирует событие «клавиша мышки нажата» (mouse press). Путем переопределения функции QWidget::mousePressEvent мы можем обработать это событие и установить или стереть пиксель изображения, находящийся под курсором мышки.

Если пользователь нажал левую кнопку мышки, мы вызываем закрытую функцию setImagePixel c true в качестве второго аргумента, указывая на необходимость установки цвета пикселя на текущий цвет пера. Если пользователь нажал правую кнопку мышки, мы также вызываем функцию setImagePixel, но передаем false для стирания пикселя.

80 void IconEditor::mouseMoveEvent(QMouseEvent *event)

81 {

82 if (event->buttons & Qt::LeftButton) {

83 setImagePixel(event->pos, true);

84 } else if (event->buttons & Qt::RightButton) {

85 setImagePixel(event->pos, false);

86 }

87 }

Функция mouseMoveEvent обрабатывает события «перемещение мышки». По умолчанию эти события генерируются только при нажатой пользователем кнопки мышки. Можно изменить этот режим работы с помощью вызова функции QWidget::setMouseTracking, но нам не нужно это делать в нашем примере.

Как при нажатии левой или правой кнопки мышки устанавливается или стирается пиксель, так и при удерживании нажатой кнопки над пикселем тоже будет устанавливаться или стираться пиксель. Поскольку допускается удерживать нажатыми одновременно несколько кнопок, возвращаемое функцией QMouseEvent::buttons значение представляет собой результат логической операции поразрядного ИЛИ для кнопок. Мы проверяем нажатие определенной кнопки при помощи оператора & и при наличии соответствующего состояния вызываем функцию setImagePixel.

88 void IconEditor::setImagePixel(const QPoint &pos, bool opaque)

89 {

90 int i = pos.x / zoom;

91 int j = pos.y / zoom;

92 if (image.rect.contains(i, j)) {

93 if (opaque) {

94 image.setPixel(i, j, penColor.rgba);

95 } else {

96 image.setPixel(i, j, qRgba(0, 0, 0, 0));

97 }

98 update(pixelRect(i, j));

99 }

100 }

Функция setImagePixel вызывается из mousePressEvent и mouseMoveEvent для установки или стирания пикселя. Параметр pos определяет положение мышки на виджете.

На первом этапе надо преобразовать положение мышки из системы координат виджета в систему координат изображения. Это достигается путем деления координат положения мышки x и y на коэффициент масштабирования. Затем мы проверяем попадание точки в нужную область. Это легко сделать при помощи функций QImage::rect и QRect::contains; фактически здесь проверяется попадание значения переменной i в промежуток между 0 и значением image.width — 1, а переменной j — в промежуток между 0 и значением image.height — 1.

В зависимости от значения параметра opaque мы устанавливаем или стираем пиксель в изображении. При стирании пиксель фактически становится прозрачным. Для вызова QImage::setPixel мы должны преобразовать перо QColor в 32-битовое значение ARGB. В конце мы вызываем функцию update с передачей объекта QRect, задающего область перерисовки.

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

Обычно при изменении размеров виджета Qt генерирует событие рисования для всей видимой области виджета. Но если виджет создается с установленным флажком Qt::WA_StaticContents, область рисования ограничивается не показанными ранее пикселями. Это подразумевает, что, если размеры виджета уменьшаются, событие рисования вообще не будет сгенерировано.

Рис. 5.5. Изменение размеров виджета Qt::WA_StaticContents.

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

Интеграция пользовательских виджетов в Qt Designer

Прежде чем мы сможем использовать пользовательские виджеты в Qt Designer, мы должны сделать так, что Qt Designer будет знать о них. Для этого существует два способа: метод «продвижения» (promotion) и метод подключения (plugin).

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

Ниже приводится порядок действий при интеграции данным методом виджета HexSpinBox:

1. Создайте наборный счетчик QSpinBox, перетаскивая его с панели виджетов Qt Designer на форму.

2. Щелкните правой клавишей мышки по наборному счетчику и выберите пункт контекстного меню Promote to Custom Widget (Преобразовать в пользовательский виджет).

3. Заполните в появившемся диалоговом окне поле названия класса значением «HexSpinBox» и поле заголовочного файла значением «hexspinbox.h».

Поделиться:
Популярные книги

Город костей

Уэллс Марта
Фантастика:
научная фантастика
6.25
рейтинг книги
Город костей

Убийца

Бубела Олег Николаевич
3. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.26
рейтинг книги
Убийца

Ученик

Первухин Андрей Евгеньевич
1. Ученик
Фантастика:
фэнтези
6.20
рейтинг книги
Ученик

Неправильный лекарь. Том 1

Измайлов Сергей
1. Неправильный лекарь
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Неправильный лекарь. Том 1

Я князь. Книга XVIII

Дрейк Сириус
18. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я князь. Книга XVIII

Третий Генерал: Том V

Зот Бакалавр
4. Третий Генерал
Фантастика:
городское фэнтези
аниме
сказочная фантастика
попаданцы
5.00
рейтинг книги
Третий Генерал: Том V

Кодекс Охотника. Книга X

Винокуров Юрий
10. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
6.25
рейтинг книги
Кодекс Охотника. Книга X

Сирийский рубеж

Дорин Михаил
5. Рубеж
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Сирийский рубеж

Обгоняя время

Иванов Дмитрий
13. Девяностые
Фантастика:
попаданцы
5.00
рейтинг книги
Обгоняя время

Везунчик. Дилогия

Бубела Олег Николаевич
Везунчик
Фантастика:
фэнтези
попаданцы
8.63
рейтинг книги
Везунчик. Дилогия

Кодекс Крови. Книга ХVII

Борзых М.
17. РОС: Кодекс Крови
Фантастика:
попаданцы
аниме
фэнтези
5.25
рейтинг книги
Кодекс Крови. Книга ХVII

Группа крови на рукаве

Вязовский Алексей
1. ГК
Фантастика:
боевая фантастика
попаданцы
альтернативная история
6.40
рейтинг книги
Группа крови на рукаве

Этот мир не выдержит меня. Том 3

Майнер Максим
3. Первый простолюдин в Академии
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Этот мир не выдержит меня. Том 3

Ученик. Книга третья

Первухин Андрей Евгеньевич
3. Ученик
Фантастика:
фэнтези
7.64
рейтинг книги
Ученик. Книга третья