Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: SABROG от Январь 21, 2009, 16:16



Название: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: SABROG от Январь 21, 2009, 16:16
(http://img186.imageshack.us/img186/6038/animatenc5.gif)

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

При рисовании на 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 файлом доступен в аттаче.


Название: Re: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: SABROG от Январь 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++));
 


Название: Re: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: Dendy от Январь 21, 2009, 16:39
В первом случае подозреваю что нужно делать не rect() (я так понимаю this - это QWidget), а image.rect(), иначе центр мог оказаться за пределами картинки, если размеры окна и картинки не совпадают.
Во втором случае текст рисуется, но за пределами картинки, начиная от базовой линии и вверх. Нужно делать:

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


Название: Re: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: SABROG от Январь 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 - остался.


Название: Re: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: SABROG от Январь 22, 2009, 00:28
Похоже другого варианта кроме как присвоить новый QImage - старому нет.

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

(http://img48.imageshack.us/img48/6757/weirdpaintyz2.png)

Вызывал оригинальный обработчик QWidget::paintEvent() перед отрисовкой новой порции, но не помогает. В чем может быть проблема?


Название: Re: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: Dendy от Январь 22, 2009, 01:32
А весь код можно?


Название: Re: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: SABROG от Январь 22, 2009, 01:40
А весь код можно?

В первом посте.


Название: Re: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: Dendy от Январь 22, 2009, 02:06
Глянем. А пока совет - наружу из архива лучше чтобы торчала ровно одна директория. А файлы и поддиректории уже внутри.


Название: Re: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: Dendy от Январь 22, 2009, 02:14
Картинка создаётся на неинициализорованном куске памяти, изначально там мусор. Каждый раз вы дорисовываете белую пляму цифр поверх старой, в результате у вас в картике - сумма белых плям.


Название: Re: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: SABROG от Январь 22, 2009, 02:44
Цитировать
Глянем. А пока совет - наружу из архива лучше чтобы торчала ровно одна директория. А файлы и поддиректории уже внутри.
Об этом я знаю, проблема была в том, что в директории находилась куча файлов после компиляции. Я вручную выделял нужные файлы и потом их сжал.

Цитировать
Картинка создаётся на неинициализорованном куске памяти, изначально там мусор. Каждый раз вы дорисовываете белую пляму цифр поверх старой, в результате у вас в картике - сумма белых плям.
Я пытался использовать ARGB вместо RGB, чтобы в fillRect указав Qt::transparency стереть все лишнее оставив только прозрачность. Этот вариант не прошел. И я не понимаю откуда берется сумма пикселей, если я каждый раз создаю новый экземпляр QImage и присваиваю его старому. В документации написано, что это работает как копирование, т.е. старый экземпляр уничтожается.


Название: Re: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: Dendy от Январь 22, 2009, 03:42
Цитировать
Об этом я знаю, проблема была в том, что в директории находилась куча файлов после компиляции. Я вручную выделял нужные файлы и потом их сжал.

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

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

В том коде что в архиве такого нет - используется всё тот же экземпляр. Да, старый экземпляр картинки уничтожается при присвоении. Но это не будет работать как очистка буфера, в новой картинке будет мусор, очистить который проще всего через QImage::fill( 0 ).


Название: Re: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: SABROG от Январь 22, 2009, 09:06
Да, действительно. Если стоит формат RGB, то картинка заполняется черным цветом, если ARGB, то становится прозрачной. Вроде бы все работает. Спасибо.

А чем мне CMake поможет? Он чистить папки умеет или сжимать :) ?


Название: Re: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: SABROG от Январь 22, 2009, 14:34
Еще вопросик. QImage - в формате ARGB, т.е. поддерживает прозрачность. И я на нем рисую текст с альфаканалом:

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

Далее я использую setMask для виджета, чтобы обрезать окошко по картинке. Но я хочу, чтобы background окошка стал таким же прозрачным как текст в QImage, т.е. имел тот же альфаканал. Т.е. должно получится тоже самое, что и при использовании метода setWindowOpacity(), только прозрачность должна браться именно с QImage. Не знаю в какую сторону рыть.


Название: Re: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: Dendy от Январь 22, 2009, 15:30
А чем мне CMake поможет? Он чистить папки умеет или сжимать :) ?

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

Маска в Windows не бывает полупрозрачной, каждый пиксель или полностью прозрачен или наоборот.


Название: Re: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: SABROG от Январь 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? Т.е., чтобы можно было регулировать степень прозрачности картинки=окна каждого пикселя.

(http://img120.imageshack.us/img120/171/opacityhb9.jpg)

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


Название: Re: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: Dendy от Январь 22, 2009, 17:26
Альфа-канал может быть только у всего окна целиком, а не по отдельности. Во всяком случае насколько знаю я. Без конпозитного оконного менеджера вы этого обойти, увы, не сможете. Совет - не извращайтесь, сосредоточтесь на главной цели вашей программы.

По поводу системы сборки. То что вы написали - это костыль в QMake. Продукты компиляции всё равно гадятся в исходники: tmp/*, Makefile, Makefile.Release, Makefile.Debug. Будет конфигураций больше - мусора будет пропорционально. Вообще не хотелось бы офтопить. Лучше оформлю это как статью позже на Вики.


Название: Re: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: SABROG от Январь 22, 2009, 21:13
Значит остается только один вариант сделать такое. Это grabWidget() на desktop, чтобы содрать кусок экрана под окном?

Хотя и это не вариант, т.к. само окно придется прятать на время пока идет "съемка".


Название: Re: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: Dendy от Январь 22, 2009, 21:59
Это решение содержит много недостатков, у вас есть шанс промучиться и не прийти к удобоваримому результату. Ну не предусмотрено это системой. Значит пользователь этого не ждёт. Решение нужно строить ровными полностью документированными кирпичами.


Название: Re: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: Tonal от Январь 23, 2009, 09:16
Маска в Windows не бывает полупрозрачной, каждый пиксель или полностью прозрачен или наоборот.
Я добивался отработки альфа по каждому пикселю маски под виндой с помощью UpdateLayeredWindow.
По крайней мере на ХР и висте это работает.
Поддерживает ли это Qt я не проверял.


Название: Re: [Qt 4.4.3] QPainter QImage drawText.
Отправлено: SABROG от Январь 23, 2009, 09:56
Оказывается это в FAQ'е у троллей есть (http://www.qtsoftware.com/developer/faqs/faq.2007-02-08.3940505976)

Если я правильно все понял, то есть еще вариант с созданием основного окна и дочернего. Основное сделать прозрачным, а дочернее уже альфить как вздумается.