Russian Qt Forum
Ноябрь 25, 2024, 02:51 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: [Qt 4.4.3] QPainter QImage drawText.  (Прочитано 17587 раз)
SABROG
Гость
« : Январь 21, 2009, 16:16 »



Эксперименитурю с анимацией. Возникли следующие неразрешенные вопросы:

При рисовании на QPixmap ничего не рисуется и выдается в консоль:
Код
C++ (Qt)
QPainter::begin: Paint device returned engine == 0, type: 2
QPainter::end: Painter not active, aborted
 

Поэтому я использую QImage. Но я хочу, чтобы размер QImage динамически менялся в соответствии с размером QWidget'a. scaled не подходит, т.к. не работает с пустым изображением, да и по логике нужен совсем не для resize'a.

Как изменить размер QImage?

Почему при использовании метода:

Код
C++ (Qt)
painter.drawText(rect(), QString::number(counter++));
 

текст рисуется на QImage, а при использовании следующих методов - нет?

Код
C++ (Qt)
painter.drawText(rect(), Qt::AlignCenter, QString::number(counter++));
 

Код
C++ (Qt)
painter.drawText(0, 0, QString::number(counter++));
 

Компилируемый исходный код с .pro файлом доступен в аттаче.
Записан
SABROG
Гость
« Ответ #1 : Январь 21, 2009, 16:35 »

С методом:

Код
C++ (Qt)
painter.drawText(0, 0, QString::number(counter++));
 

Разобрался. Тут y - baseline (левый нижний угол начала текста). Поэтому надо корректировать y еще и на высоту шрифта.

С этим остается непонятка, если размер виджета больше размера QImage, то картинка не отрисовывается.
Код
C++ (Qt)
painter.drawText(rect(), Qt::AlignCenter, QString::number(counter++));
 
Записан
Dendy
Гость
« Ответ #2 : Январь 21, 2009, 16:39 »

В первом случае подозреваю что нужно делать не rect() (я так понимаю this - это QWidget), а image.rect(), иначе центр мог оказаться за пределами картинки, если размеры окна и картинки не совпадают.
Во втором случае текст рисуется, но за пределами картинки, начиная от базовой линии и вверх. Нужно делать:

Код
C++ (Qt)
painter.drawText( 0, painter.font().ascent(), QString::number(counter++) );
Записан
SABROG
Гость
« Ответ #3 : Январь 21, 2009, 16:44 »

Всё всем спасибо. Вопрос решен, сам же я и накосячил. Надо было вместо

Код
C++ (Qt)
painter.drawText(rect(), Qt::AlignCenter, QString::number(counter++));
 

Писать.

Код
C++ (Qt)
painter.drawText(image.rect(), Qt::AlignCenter, QString::number(counter++));
 

Просто текст центрировался за пределами экрана.

В итоге 2 косяка: кривые руки и плохое понимание документации.

Кстати странно, что когда я пытался подобное рисовать на виджет, то текст рисовался нормально несмотря на то, что baseline (y) был нулевой.
---
В принципе вопрос с изминением размера QImage - остался.
« Последнее редактирование: Январь 21, 2009, 17:00 от SABROG » Записан
SABROG
Гость
« Ответ #4 : Январь 22, 2009, 00:28 »

Похоже другого варианта кроме как присвоить новый QImage - старому нет.

Еще такой вопрос. Я комментирую строку с fillRect, чтобы текст мог рисоваться на оригинальном фоне. Но к сожалению я получаю такую картину:



Вызывал оригинальный обработчик QWidget::paintEvent() перед отрисовкой новой порции, но не помогает. В чем может быть проблема?
Записан
Dendy
Гость
« Ответ #5 : Январь 22, 2009, 01:32 »

А весь код можно?
Записан
SABROG
Гость
« Ответ #6 : Январь 22, 2009, 01:40 »

А весь код можно?

В первом посте.
Записан
Dendy
Гость
« Ответ #7 : Январь 22, 2009, 02:06 »

Глянем. А пока совет - наружу из архива лучше чтобы торчала ровно одна директория. А файлы и поддиректории уже внутри.
Записан
Dendy
Гость
« Ответ #8 : Январь 22, 2009, 02:14 »

Картинка создаётся на неинициализорованном куске памяти, изначально там мусор. Каждый раз вы дорисовываете белую пляму цифр поверх старой, в результате у вас в картике - сумма белых плям.
Записан
SABROG
Гость
« Ответ #9 : Январь 22, 2009, 02:44 »

Цитировать
Глянем. А пока совет - наружу из архива лучше чтобы торчала ровно одна директория. А файлы и поддиректории уже внутри.
Об этом я знаю, проблема была в том, что в директории находилась куча файлов после компиляции. Я вручную выделял нужные файлы и потом их сжал.

Цитировать
Картинка создаётся на неинициализорованном куске памяти, изначально там мусор. Каждый раз вы дорисовываете белую пляму цифр поверх старой, в результате у вас в картике - сумма белых плям.
Я пытался использовать ARGB вместо RGB, чтобы в fillRect указав Qt::transparency стереть все лишнее оставив только прозрачность. Этот вариант не прошел. И я не понимаю откуда берется сумма пикселей, если я каждый раз создаю новый экземпляр QImage и присваиваю его старому. В документации написано, что это работает как копирование, т.е. старый экземпляр уничтожается.
Записан
Dendy
Гость
« Ответ #10 : Январь 22, 2009, 03:42 »

Цитировать
Об этом я знаю, проблема была в том, что в директории находилась куча файлов после компиляции. Я вручную выделял нужные файлы и потом их сжал.

Могу сказать только одно. Just Use CMake!

Цитировать
И я не понимаю откуда берется сумма пикселей, если я каждый раз создаю новый экземпляр QImage и присваиваю его старому.

В том коде что в архиве такого нет - используется всё тот же экземпляр. Да, старый экземпляр картинки уничтожается при присвоении. Но это не будет работать как очистка буфера, в новой картинке будет мусор, очистить который проще всего через QImage::fill( 0 ).
Записан
SABROG
Гость
« Ответ #11 : Январь 22, 2009, 09:06 »

Да, действительно. Если стоит формат RGB, то картинка заполняется черным цветом, если ARGB, то становится прозрачной. Вроде бы все работает. Спасибо.

А чем мне CMake поможет? Он чистить папки умеет или сжимать Улыбающийся ?
Записан
SABROG
Гость
« Ответ #12 : Январь 22, 2009, 14:34 »

Еще вопросик. QImage - в формате ARGB, т.е. поддерживает прозрачность. И я на нем рисую текст с альфаканалом:

Код
C++ (Qt)
painter.setPen(QColor(255, 0, 0, 10));
 

Далее я использую setMask для виджета, чтобы обрезать окошко по картинке. Но я хочу, чтобы background окошка стал таким же прозрачным как текст в QImage, т.е. имел тот же альфаканал. Т.е. должно получится тоже самое, что и при использовании метода setWindowOpacity(), только прозрачность должна браться именно с QImage. Не знаю в какую сторону рыть.
Записан
Dendy
Гость
« Ответ #13 : Январь 22, 2009, 15:30 »

А чем мне CMake поможет? Он чистить папки умеет или сжимать Улыбающийся ?

CMake не гадит в дерево исходников в отличии от QMake. По тому же принципу работает, к примеру, Xcode.

Маска в Windows не бывает полупрозрачной, каждый пиксель или полностью прозрачен или наоборот.
Записан
SABROG
Гость
« Ответ #14 : Январь 22, 2009, 17:15 »

Ну я обычно это обхожу таким образом в .pro файле:

Код:
CONFIG(debug, debug|release) { 
    CONFIG += console
    DEFINES += debug__
    QMAKE_CXXFLAGS_DEBUG += -pg
    QMAKE_LFLAGS_DEBUG += -pg
    OBJECTS_DIR = tmp/debug
    MOC_DIR = tmp/debug
    UI_HEADERS_DIR = tmp/debug
    RCC_DIR += tmp/debug
}
else {
    DEFINES += release__
    OBJECTS_DIR = tmp/release
    MOC_DIR = tmp/release
    UI_HEADERS_DIR = tmp/release
    RCC_DIR += tmp/release
}

Т.е. в папочке с проектом создается временная папка tmp куда все результаты и складываются. Но обычно это уже прописывается на более позднем этапе, когда мне становится понятно, что есть смысл продолжать развивать программу.

Т.е. подобной картинке кроме как с setWindowOpacity() я никаким образом получить не смогу в paintEvent? Т.е., чтобы можно было регулировать степень прозрачности картинки=окна каждого пикселя.



В данном случае число 385 - окно с setMask. Прозрачность достигается путем вызова setWindowOpacity(), при этом цвет текста также имеет альфаканал, но он не влияет на прозрачность окна, а хотелось бы.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.221 секунд. Запросов: 21.