- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
QT 4: программирование GUI на С++ - Жасмин Бланшет
Шрифт:
Интервал:
Закладка:
32 void IconEditor::setZoomFactor(int newZoom)
33 {
34 if (newZoom < 1)
35 newZoom = 1;
36 if (newZoom != zoom) {
37 zoom = newZoom;
38 update();
39 updateGeometry();
40 }
41 }
Функция setZoomFactor() устанавливает масштабный коэффициент изображения. Для предотвращения деления на нуль мы корректируем всякое значение, меньшее, чем 1. Мы опять вызываем функции update() и updateGeometry() для перерисовки виджета и уведомления всех менеджеров компоновки об изменении идеального размера.
Функции penColor(), iconImage() и zoomFactor() реализуются в заголовочном файле как встроенные функции.
Теперь мы рассмотрим программный код функции paintEvent(). Эта функция играет очень важную роль в классе IconEditor. Она вызывается всякий раз, когда требуется перерисовать виджет. Используемая по умолчанию ее реализация в QWidget ничего не делает, оставляя виджет пустым.
Так же как рассмотренная нами в главе 3 функция closeEvent(), функция paintEvent() является обработчиком события. В Qt предусмотрено много других обработчиков событий, каждый из которых относится к определенному типу события. Обработка событий подробно рассматривается в главе 7.
Существует множество ситуаций, когда генерируется событие рисования (paint) и вызывается функция paintEvent():
• при первоначальном выводе на экран виджета система автоматически генерирует событие рисования, чтобы виджет нарисовал сам себя;
• при изменении размеров виджета система генерирует событие рисования;
• если виджет перекрывается другим окном и затем вновь оказывается видимым, генерируется событие рисования для областей, которые закрывались (если только система управления окнами не сохранит закрытую область).
Мы можем также принудительно сгенерировать событие рисования путем вызова функции QWidget::update() или QWidget::repaint(). Различие между этими функциями следующее: repaint() приводит к немедленной перерисовке, а функция update() просто передает событие рисования в очередь событий, обрабатываемых Qt. (Обе функции ничего не будут делать, если виджет невидим на экране.) Если update() вызывается несколько раз, Qt из нескольких следующих друг за другом событий рисования делает одно событие для предотвращения мерцания. В классе IconEditor мы всегда используем функцию update().
Ниже приводится программный код:
42 void IconEditor::paintEvent(QPaintEvent *event)
43 {
44 QPainter painter(this);
45 if (zoom >= 3) {
46 painter.setPen(palette().foreground().color());
47 for (int i = 0; i <= image.width(); ++i)
48 painter.drawLine(zoom * i, 0,
49 zoom * i, zoom * image.height());
50 for (int j = 0; j <= image.height(); ++j)
51 painter.drawLine(0, zoom * j,
52 zoom * image.width(), zoom * j);
53 }
54 for (int i = 0; i < image.width(); ++i) {
55 for (int j = 0; j < image.height(); ++j) {
56 QRect rect = pixelRect(i, j);
57 if (!event->region().intersect(rect).isEmpty()) {
58 QColor color = QColor::fromRgba(image.pixel(i, j));
59 painter.fillRect(rect, color);
60 }
61 }
62 }
63 }
Мы начинаем с построения объекта QPainter нашего виджета. Если масштабный коэффициент равен или больше 3, мы вычерчиваем с помощью функции QPainter::drawLine() горизонтальные и вертикальные линии сетки.
Вызов функции QPainter::drawLine() имеетследующий формат:
painter.drawLine(x1, y1, x2, y2);
где (x1, y1) задает положение одного конца линии и (x2, y2) задает положение другого конца линии. Существует перегруженный вариант функции, которая принимает два объекта типа QPoint вместо четырех целых чисел.
Пиксель в верхнем левом углу виджета Qt имеет координаты (0, 0), а пиксель в нижнем правом углу имеет координаты (width() — 1, height() — 1). Это напоминает обычную декартовскую систему координат, но только перевернутую сверху вниз. Мы можем изменить систему координат в QPainter, трансформируя ее такими способами, как смещение, масштабирование, вращение и отсечение. Эти вопросы рассматриваются в главе 8 («Графика 2D и 3D»).
Рис. 5.3. Вычерчивание линии при помощи QPainter.
Перед вызовом в QPainter функции drawLine() мы устанавливаем цвет линии, используя функцию setPen(). Мы могли бы жестко запрограммировать цвет (например, черный или серый), но лучше использовать палитру виджета.
Каждый виджет имеет палитру, которая определяет назначение цветов. Например, предусмотрен цвет фона виджетов (обычно светло—серый) и цвет текста на этом фоне (обычно черный). По умолчанию палитра виджета адаптирована под схему цветов оконной системы. Используя цвета из палитры, мы обеспечим в IconEditor учет пользовательских настроек.
Палитра виджета состоит из трех цветовых групп: активной, неактивной и нерабочей. Цветовая группа выбирается в зависимости от текущего состояния виджета:
• группа Active используется для виджетов текущего активного окна;
• группа Inactive используется виджетами других окон;
• группа Disabled используется отключенными виджетами любого окна.
Функция QWidget::palette() возвращает палитру виджета в виде объекта QPalette. Цветовые группы определяются как элементы перечисления типа QPalette::QColorGroup. Удобная функция QWidget::colorGroup() возвращает правильную цветовую группу текущего состояния виджета, и поэтому нам редко придется выбирать цвет непосредственно из палитры.
Когда нам нужно получить соответствующую кисть или цвет для рисования, правильный подход связан с применением текущей палитры, полученной функцией QWidget::palette(), и соответствующей ролевой функции, например QPalette::foreground(). Каждая ролевая функция возвращает кисть, что обычно и требуется, однако если нам нужен только цвет, его можно извлечь из кисти, как мы это делали в paintEvent(). По умолчанию возвращаемые кисти соответствуют состоянию виджета, поэтому нам не надо указывать цветовую группу.
Функция paintEvent() завершает рисование изображения. Вызов IconEditor::pixelRect() возвращает QRect, который определяет область перерисовки. Мы не выдаем пиксели, которые попадают за пределы данной области, обеспечивая простую оптимизацию.
Рис. 5.4. Вычерчивание прямоугольника при помощи QPainter.
Мы вызываем QPainter::fillRect() для вывода на экран масштабируемого пикселя. QPainter::fillRect() принимает QRect и QBrush. Передавая QColor в качестве кисти, мы обеспечиваем равномерное заполнение области.
64 QRect IconEditor::pixelRect(int i, int j) const
65 {
66 if (zoom >= 3) {
67 return QRect(zoom * i + 1, zoom * j + 1, zoom - 1, zoom - 1);
68 } else {
69 return QRect(zoom * i, zoom * j, zoom, zoom);
70 }
71 }
Функция pixelRect() возвращает объект QRect, который может использоваться функцией QPainter::fillRect(). Параметры i и j являются координатами пикселя в QImage, а не в виджете. Если коэффициент масштабирования равен 1, обе системы координат будут полностью совпадать.
Конструктор QRect имеет синтаксис QRect(x, у, width, height), где (x, у) являются координатами верхнего левого угла прямоугольника, a width и height являются размерами прямоугольника (шириной и высотой). Если коэффициент масштабирования равен не менее 3, мы уменьшаем размеры прямоугольника на один пиксель по горизонтали и по вертикали, чтобы не загораживать линии сетки.
72 void IconEditor::mousePressEvent(QMouseEvent *event)
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 для стирания пикселя.

