C++ — Qt C++ не отображается картинка


C++ — Qt C++ не отображается картинка

Статья «нулевого уровня», но пару примеров кода содержит :)

1. Общие принципы

Общий порядок работы с графикой в QT похож на другие современные среды программирования. В основе работы лежит взаимодействие 3 классов:

  • QPainter – «рисовальщик» QT, класс-исполнитель команд рисования;
  • QPaintEngine – «движок» рисования, обычно не используемый из кода непосредственно. Он бывает нужен программисту лишь при создании собственных контекстов рисования, отсутствующих в системе;
  • QPaintDevice – контекст рисования (канва), который можно понимать как графическое «полотно», состоящее из пикселов.

В обычных случаях программе достаточно «захватить» адрес объекта контекста, отрисовать нужные графические примитивы и освободить контекст:

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

Как и в других подобных графических системах, для рисования используются 2 основных инструмента:

  • Перо QPen – для рисования контуров;
  • Кисть QBrush – для заполнения контуров цветом.

Непосредственно отрисовкой занимаются методы класса QPainter с названиями на draw (drawLine, drawRect, drawPolygon, drawEllipse) или fill (fillRect, fillPath). Кроме настроек пера и кисти, этим методам часто требуется информация о координатах точек, размерах прямоугольников, текущих цветах и т.п. Для хранения всей этой информации в QT предусмотрен ряд геометрических классов, которые ничего не рисуют, но хранят описания размеров или расположений графических объектов. Большинство геометрических классов реализованы «дважды», например, класс QPoint работает с целочисленными координатами точек на плоскости, а QPointF – с вещественными:

Целочисленные и вещественные координаты точки на плоскости

. x (), . y () – получение координат;

. setX (), . setY () – установка координат.

В классах определены сравнения, арифметические действия над координатами

Размер, то есть, совокупность ширины и высоты

. width (), . height () – получить размеры;

. setWidth (), . setHeight () – установить размеры;

. scale () – масштабировать размер.

Прямоугольник, фактически, это » точка+размер «

См. QPoint , QSize

Отрезки на плоскости

. x 1(), . y 1(), . x 2(), . y 2() – координаты начала и конца отрезка;


. dx (), . dy () – проекции на оси 0 X и 0 Y

Многоугольник на плоскости, фактически, массив точек (координат вершин)

. point ( i ) – вернуть i — ую точку

Цвет в модели RGB (или HSV )

. setRgb ( r,g,b ) установить интенсивности цветов;

. red (), . green , . blue (), . alpha () – получить интенсивности цветов и прозрачность

В классе QPainter также определены удобные методы для манипулирования с системой координат:

  • translate – сдвинуть начало координат в указанную точку;
  • scale – масштабировать систему координат;
  • rotate – повернуть систему координат;
  • shear – исказить систему координат (выполнить скос);
  • save, restore – сохранить/восстановить состояние рисовальщика.

В большинстве случаев при отрисовке объектов удобнее пользоваться этими методами, чем высчитывать всё в «абсолютных координатах» канвы. Например, мы не меняли геометрию треугольника, определённого в функции drawTriangle и не высчитывали при каждой отрисовке новых координат его вершин:

2. Работа с графической канвой

Создадим проект на основе класса QWidget (добавились файлы main.cpp, widget.h, widget.cpp). Так как отрисовка выполняется по событию paintEvent, в заголовочном файле widget.h нам понадобится добавить прототип виртуального метода paintEvent, предусмотренного в каждом виджете. Чтобы виджет мог рисовать на канве, он должен переопределить этот метод:

В файле widget.cpp нам остается написать реализацию метода. Покажем простейшие действия с кистью, пером и строкой текста:

Теперь класс Widget может рисовать на своей канве. Так как событие paintEvent происходит, в том числе, при изменении размеров окна виджета, картинка всё время будет соответствовать окну формы.

На самом деле, конечно, painter надо прописать в заголовочном файле класса, инициализировать в конструкторе класса, а не создавать каждый раз заново при перерисовке формы. Здесь и выше так сделано только для краткости примера.

3. Работа с изображениями

QT может как записывать, так и загружать файлы основных растровых форматов, включая PNG, BMP, ICO, TIFF, JPEG, GIF и некоторые другие. При этом поддерживается контекстно-независимое представление графики. Фактически, это означает, что данные изображений помещаются в массивы, содержащие данные об отдельных пикселах рисунка. Основным классом представления изображений является QImage. Этот класс унаследован от контекста рисования QPaintDevice, что позволяет использовать все методы рисования, определённые в QPainter. Метод класса format() позволяет узнать формат текущего изображения, а метод convertToFormat() – изменить его, вернув новый объект класса QImage. Некоторые значения перечисления Format указаны ниже:

  • Format_Invalid — формат неверен;
  • Format_Mono – монохромное изображение с 1 битом на пиксел;
  • Format_Index8 – данные представляют собой 8-битные индексы цветовой палитры;
  • Format_RGB32 – каждый пиксел представлен 32 битами (интенсивности красного, зелёного и синего, плюс значение альфа-канала, всегда равное 0xFF, то есть, прозрачность не поддерживается);
  • Format_ARGB32 – 32 бита на пиксел с поддержкой альфа-канала прозрачности.

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

Цукерберг рекомендует:  Концепция постраничной навигации (с использованием слайдера jQuery)

Загрузить изображение можно, передав конструктору путь к нужному файлу:

или воспользовавшись методом load:

Как видно из кода, отобразить изображение можно методом drawImage класса QPainter. Показать часть изображения можно с помощью дополнительных параметров метода.

Папка, которая является текущей, в общем случае зависит от проекта. Обычно это та папка, где находится файл Makefile проекта.


Сохранить изображение может метод save:

Сохранение произойдёт в ту папку, которая является текущей в вашей конфигурации проекта.

Для чтения отдельных пикселов удобен метод pixel:

Записать пикселы можно с помощью метода setPixel:

Показанный код рисует линейный градиент в окне формы, для работы нужны директивы

В классе QImage реализован ряд методов для редактирования изображений:

  • invertPixels – позволяет инвертировать цвета пикселов и/или альфа-канал;
  • scaled – позволяет масштабировать изображение;
  • mirrored – выполняет зеркальное отражение картинки по горизонтали и/или вертикали.

Класс контекстно-зависимого представления изображений QPixmap также унаследован от QPaintDevice. Его использование целесообразно там, где нужен промежуточный буфер для рисования или критична скорость отрисовки графических объектов. Существует также отдельный класс-потомок QBitmap для работы с монохромными изображениями.

4. Построение графиков и диаграмм

Хорошее введение в тему даёт эта статья.

5. «Продвинутый» пример рисования мышью в QT

По всем правилам создаём графическую сцену, таймер и пример простейшей «рисовалки» нажатой левой кнопкой мыши.

В качестве задания по теме подойдёт примерно следующее:

Напишите виджет, позволяющий:

  • Загружать изображения и отслеживать цвета отдельных пикселов на них;
  • Добавлять на изображения графические примитивы по выбору пользователя и сохранять изменённую картинку;
  • Строить график выбранной функции.

27.04.2020, 16:12; рейтинг: 32289

QSplashScreen: Начальный экран-заставка для Qt-приложения

Если приложение запускается слишком долго, то пользователь может решить, что оно не работает вовсе. Чтобы снять такие опасения, принято использовать экраны-заставки, называемые Splash Screen. Подобные заставки вы могли видеть при запуске Eclipse, Visual Studio, Adobe Photoshop и других известных программ.

Экраны заставки решают две задачи:

  1. Показывают, что приложение действительно работает и запускается;
  2. Дают примерную оценку готовности приложения к работе.


Создадим свой Splash Screen для Qt-приложения с помощью QSplashScreen . В результате получим следующее:

QSplashScreen представляет собой достаточно примитивный виджет, который умеет отображать изображение QPixmap , а также выводить текст в нужном месте. На нашем экране-заставке мы отобразим Progress Bar и текстовое сообщение с информацией о готовности приложения к работе (в процентах), а также логотип, копирайт и название программы (для целостности).

Заготовку экрана-заставки нарисуем в любом графическом редакторе:

Мы выделили место под Progress Bar, который будем заполнять сами в зависимости от степени готовности с помощью QPainter . Заметим, что для этой цели можно использовать и стандартный вид QProgressBar , как мы делали это в статье QProgressBar в таблице QTableView.

Приложение состоит из единственного файла main.cpp :

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

C++ — Qt C++ не отображается картинка

3617 просмотра

2 ответа

702 Репутация автора

Я новичок в Qt, у меня есть ярлык с фоновым изображением. Фоновое изображение отображается нормально, но не может отображаться поверх изображения. Как это сделать? Веди меня. Ниже приведен мой код, как я реализовал:

Я пытался QPalette отобразить текст, но если я использую QPalette только текст, отображается, изображение не отображается. Я попробовал QPalette так:

Ответы (2)

3 плюса

3864 Репутация автора

Вы можете поместить текст на свой QImage (не на а QLabel ), а после него позвонить setPixmap() на ваш лейбл. Попробуйте что-то вроде этого:

Автор: Ilya Размещён: 18.09.2015 08:40

3 плюса

1616 Репутация автора

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

Масштабирование изображения в QW >

В этой теме 1 ответ, 1 участник, последнее обновление 6 мес., 2 нед. назад.


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

Для понимания материала рекомендую прочитать следующие статьи:

  • Создание собственных виджетов с библиотекой Qt. Мы будем создавать свой виджет, работающий как QLabel , но при этом изменяющий размер картинки и располагающий ее по своему центру;
  • Собственные виджеты в Qt Designer [Qt, C++]. С помощью Qt Designer можно быстро накидать нужный нам интерфейс, но ведь он ничего не знает о нашем виджете? — во втором разделе статьи показано как решить проблему.

Начнем с функции main — ее задача создать экземпляр главного окна и запустить обработку событий:

В проект добавим форму Qt Designer — MainWindow , класс которой наследует QMainWindow. На форму кинем кнопку ( QPushButton ) с именем load и объект для отображения картинки (экземпляр QLabel ). Немного перепишем содержимое сгенерированных файлов.

В заголовочном файле:

Добавился приватный слот load_file, который будет вызываться при нажатии на кнопку.

В файле реализации:

В конструктор добавлено соединения сигнала от кнопки со слотом-обработчиком. Слот создает стандартный диалог выбора файла, одним из аргументов при этом задаются расширения открываемых файлов. Функция выбора файла возвращает путь, выбранный пользователем (или пустую строку если пользователь решил ничего не выбирать). Путь используется при конструировании объекта типа QPixmap , который передается в функцию setPixmap объекта на форме.

Цукерберг рекомендует:  Изменение размера текста на странице

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

Посмотрим как работает стандартный QLabel . Этот класс имеет метод setPixmap , который копирует переданную картинку в свой внутренний буфер и запускает обновление (метод paintEvent ). Функция paintEvent (виртуальная, можно написать свою реализацию) смотрит что для QLabel была выставлена картинка и отрисовывает ее (не так как нам надо), но кроме этого она делает еще много всего, например рисует текст, анимацию ( QMovie ) и т. п. Таким образом, если мы создадим наследника класс QLabel — то задавать нужное нам поведение надо будет в методе paintEvent . Однако, если пользователь видит, что наш класс является наследником QLabel , а значит имеет все соответствующие методы — то он может попытаться добавить на него например анимацию. Чтобы отображение этой анимации работало корректно (наш класс вел себя как полноценный QLabel ) в методе paintEvent нам будет надо вызвать QLabel::paintEvent , однако при этом все наши старания по отображению картинки пойдут на смарку — как было описано выше, он посмотрит, что был выставлен pixmap и отрисует его (не так, как мы хотим). Вывод этого сложного абзаца в том, что наследовать класс QLabel нам не стоит.

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

В класс добавлена картинка, которую будем добавлять и метод для ее установки. Реализуем методы:

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

Вернемся к QLabel . Ведь мы можем для него точно также добавить метод setScaledPixmap и хранить еще одну картинку внутри него, которую и отрисовывать в paintEvent … (я бы не писал про это, если бы не встретил такую реализацию). Да потому что наш класс ведет себя не так, как QLabel , что будет если пользователь вызовет сначала setScaledPixmap , а потом QLabel::setPixmap ? — либо нашу картинку вообще не будет видно (поверх нее будет другая), либо (если сначала вызвать QLabel::paintEvent , а потом нарисовать то, что нам надо) — нарисовано будет две разных картинки. Все это нарушает принцип подстановки Лисков:

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

qt вывод изображения

В paintEvent пишу:

.tar.bz2 проекта в студию.

Эм, в общем, ты забыл указать QPainter’у на чем он должен рисовать:
http://doc.qt.nokia.com/4.7/qpainter.html#QPainter-2


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

всем спасибо. проблема решена. qt creator создает папку с билдом

указал, я просто не весь код показал. а как считывать не из файла? потому что обновляться часто будет картинка

Я предполагал, что картинка одна и та же будет.

забей! создай ресурс запихни в него картинку, создай QLabel и в свойстве Pixmap выбери картинку. Это если ты конечно хочешь просто на форму повесить картинку. через паинтер не помню, тоже как то делал..

либо, если картинка одна, можешь сделать QPixmap членом Widget и инициализировать его в конструкторе

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

Я в курсе. И что ты предлагаешь, если файл каждый раз будет разный?

Причем тут это? Как я понял, у него будет куча файлов с именами \d+\.png, из которых он хочется сделать анимацию. Быть может я его неправильно понял.
Но таки согласен, открывать файлы в paintEvent не лучшая затея.

Предлагаешь использовать Qt3? Не кажется тебе, что это несколько радикальные меры?

предлагаю научиться пользоваться гуглом.

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

Не отображаются русские символы и буквы в программе C++ и Qt.

Отображение русских символов в Qt

Добрый день, читатель. По умолчанию русские символы в программах с использованием Qt фреймворка отображаются некорректно. Вместо них используются непонятные знаки. Эта проблема появляется при открытии исходников программ, при выводе русских букв в консоль, при выводе русских букв в виджеты (Label, PlainText и т.д.). В этой статье содержатся решения этих проблем. На сайте уже имеется статья, в которой показано решение проблемы отображения русских букв при выводе в консоль на C++.

Русские символы в исходном коде

Бывает возникает проблема с кодировкой при открытии исходных текстов программ в Qt Creator, чаще всего такая проблема возникает у пользователей Windows. Дело в том, что при написании программы исходники иногда сохраняются в одной кодировке, а редактор в Qt Creator открывает по умолчанию в другой кодировке. Из-за этого вместо русских букв появляются кракозябры или знаки вопроса. По умолчанию в настройках редактора кода Qt Creator кодировка файлов устанавливается System, т.е. кодировка операционной системы. Linux чаще всего использует UTF-8, а Windows cp1251.

Проблема с кодировкой в редакторе Qt Creator

Цукерберг рекомендует:  Образование - Вопрос по поводу IT образования.

Для решения проблемы в верхнем меню Qt Creator следует выбрать Инструменты(Tools) — Параметры…(Settings…). В открывшемся окне слева в списке найти и выбрать Текстовый редактор(Text Editor), далее выбираем вкладку Поведение(Behavior). Находим группу настроек Кодировки файлов(Encoding files) и выбираем кодировку по умолчанию(default) — UTF-8. Теперь редактор будет открывать исходники в UTF-8, исходные тексты программ чаще всего пишутся именно в этой кодировке.

После настройки редактора следует перекодировать сами исходники. Это можно сделать в Notepad++, если вы пользователь Windows.

Можно открывать файлы и в других кодировках, для этого в верхнем меню следует выбрать Правка — Выбрать кодировку, а далее найти кодировку, в которой был сохранен исходник программы.

В итоге редактор будет сохранять исходники в новых проектах в UTF-8 и корректно открывать их после.


Русские символы в виджетах Qt

Помещая русские символы в поле Text в виджете Label или в другие виджеты, можно также столкнуться с проблемой отображения русских букв. В редакторе форм русские символы в виджеты устанавливаются и отображаются нормально, а вот при установки программным путем — нет.

Поместим русские символы в виджет Label и в PushButton в редакторе форм.

Русские символы в редакторе форм Qt

Как видно, они отображаются корректно. Далее скомпилируем и запустим программу.

Урок #5 — Отображение изображения и статуса

Видеоурок

В фреймворке Qt нет компонента, который отвечает конкретно за картинки. Чтобы добавить изображение в программу необходимо добавить текстовый объект и при помощи кода разместить в нем изображение.

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

Чтобы отобразить картинку необходимо использовать класс QPixMap, а также приблизительно следующий код:

Весь этот код записан в главном методе MainWindow , который вызывается каждый раз при создании приложения.

Для работы со статус баром используется объект statusBar , который автоматически присутствует в любом пустом приложении. Чтобы поместить туда информацию необходимо воспользоваться методом showMessage.

Qt/C++ — Урок 028. Как использовать sprite картинки с помощью QPixmap

После того, как мы нарисовали sprite в прошлом уроке по работе с Adobe Illustrator, настало время применить полученную картинку при работе с Qt и добавить её в программу с помощью QPixmap. Причем, мы сделаем анимированый sprite, и посмотрим, как происходит маленький анимированый взрыв на графической сцене нашего приложения на Qt.

Структура проекта для работы с QPixmap и sprite

Структура проекта sprite_example будет следующая:

  • sprite_example.pro — профайл проект;
  • widget.h — заголовочный файл основного окна приложения;
  • widget.cpp — файл исходных кодов основного окна приложения;
  • widget.ui — файл интерфейса;
  • sprite.h — заголовочный файл класса, предназначенного для нашего спрайта, в котором будет применяться QPixmap;
  • sprite.cpp — файл исходных кодов для работы с QPixmap;
  • sprite.qrc — ресурсный файл;
  • sprite_sheet.png — наш спрайт, который мы применим для анимации.

widget.ui

Ничего особенного в этом файле нет. Просто растягиваем по всему окно объект QGraphicsView, в который поместим QGraphicsScene .

widget.h


В этом файле мы объявим объект графической сцены, в который поместим объект с QPixmap, в котором будет анимированый sprite. Только не забудьте подключить заголовочный файл sprite.h.

widget.cpp

В данном файле инициализируем графическую сцену и помещаем её в graphicsView, а также создаём объект спрайта и помещаем его на сцену.

sprite.h

А вот теперь поговорим о том, как же реализован анимированый sprite. Для этого нам понадобится заранее подготовленный спрайт, а вернее sprite sheet, который состоит из 15 кадров, расположенных в одну строку.

Технически, данный sprite sheet устанавливается в объект класса QPixmap, в котором он пролистывается слева направо с определенной периодичность. Для этого мы новый класс наследуем от QGraphicsItem и QObject, чтобы использовать сигналы и слоты . И в методе paint задаём отрисовку участка изображения sprite_sheet , который задан в ресурсном файле. Таймер управляет сменой кадров с помощью слота nextFrame(). По сигналу от таймера мы изменяем координату отрисовки участка спрайта и перерисовываем графический объект с новым кадром.

sprite.cpp

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

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

Имеется картинка нужно вывести её на экран в QT c++

QT было скачено только вчера и вообще не понимаю что и где происходит. нашла в интернесе вот такую штуку
QPixmap pic(«my1.png»);
QLabel label;
label.setPixmap(pic);

но получаю только пустую форму. сделать нужно именно в QT

QPixmap pic(«my1.png»);
QLabel *label = new QLabel(this);
label->setPixmap(pic);
label->setGeometry(50, 50, 200, 200); // устанавливаем размер
this->layout()->addWidget(label); // добавляем в layout окна

Если нужно поместить кнопку в layout установленный в дизайнере (например QGridLayout), до него можно добраться через ui:

Qt не отображает изображения PNG в Linux

У меня есть программное обеспечение, написанное с использованием Qt которое предназначено для работы как в Windows, так и в Linux.

Я использую изображения PNG в качестве значков для своих QAction , встроенных в ресурс.

У меня есть следующий каталог дерева:

Вот содержание icons.qrc :

Я объявляю свой QIcon так:

В Windows это работает хорошо, но в Linux (я пока пробовал только в Ubuntu 10.4) изображения не отображаются.

Что-нибудь особенное, что я должен сделать, чтобы это сработало? Это проблема конфигурации?

Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих