Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: ecspertiza от Апрель 05, 2013, 13:39



Название: Как сделать подложку текста ?
Отправлено: ecspertiza от Апрель 05, 2013, 13:39
Нужно сделать подложку текста на подобии такой http://joxi.ru/mKReUdg5CbAROKsVLzI. Собственно вопрос как ? :) В идеале такой текст сделать в QTextEdit, но как я понял это не реально )))) пробовал и html текст для этого задавать, но видимо css там на таком уровне не поддерживается. Затем решил написать свой QGraphicsItem у него переопределить paint и там выводить текст, но что то с помощью QPainter не удалось сделать такую подложку, видимо не хватает каких то навыков. И последнее что я испробовал это QGraphicsDropShadowEffect, он может сделать тень, но у него не получается сделать именно подложку вокруг всего текста. Есть у кого нибудь идеи ?


Название: Re: Как сделать подложку текста ?
Отправлено: _OLEGator_ от Апрель 05, 2013, 13:45
Текст рисуется два раза.
1) Увеличенный в размере белым.
2) Нормальный размер красным.
Или требуется что-то еще?

UPD.
Ну и маленькая тень снизу рисуется на 0 этапе, небольшим сдвигом вниз увеличенного текста, серым/темно-серым.


Название: Re: Как сделать подложку текста ?
Отправлено: ecspertiza от Апрель 05, 2013, 13:51
Как раз так и пробовал, у меня получилось так что при рисовании текста что больше по размеру, увеличивается все пропорционально, в том числе и расстояние между буквами. Стало быть текст что меньше просто не попадает в нужную позицию в центре. размеры текста пробовал менять и с помощью font и с помощью QTransform::scale()


Название: Re: Как сделать подложку текста ?
Отправлено: _OLEGator_ от Апрель 05, 2013, 14:03
А, ну да. Так не прокатит. Это работает только на небольших обводках.
Здесь потребуется что-то более хитрое.
А просто отрисовка текста с кистью нужной толщины не дает необходимого эффекта? Тоесть когда и заливка и кисть установлена QPainter'у.


Название: Re: Как сделать подложку текста ?
Отправлено: ecspertiza от Апрель 05, 2013, 14:04
вот и я о том же :) Сейчас пробую понять как это в qml делается у элемента Text так там, они текст выводят просто через QPixmap и рисуют по сути два пиксмапа для вывода такого стиля текста. Но как они формируют их пока понять не могу.


Название: Re: Как сделать подложку текста ?
Отправлено: Bepec от Апрель 05, 2013, 14:07
Я думаю там делается проще - каждая буква отрисовывается отдельно.

Рисуем большую, поверх маленькую. Отрисовываем. Отступаем на положенные пиксели и делаем дальше. Конечно алгоритм топорный, но, думаю, поплывёт.


Название: Re: Как сделать подложку текста ?
Отправлено: GreatSnake от Апрель 05, 2013, 14:15
И последнее что я испробовал это QGraphicsDropShadowEffect, он может сделать тень, но у него не получается сделать именно подложку вокруг всего текста. Есть у кого нибудь идеи ?
Код
C++ (Qt)
QGraphicsDropShadowEffect::setOffset( 0, 0 );
QGraphicsDropShadowEffect::setBlurRadius( 20 );
 
но край тени будет размытым.


Название: Re: Как сделать подложку текста ?
Отправлено: ecspertiza от Апрель 05, 2013, 14:46
Насчет рисовать каждую букву думается не очень хорошая идея, скажется на производительности достаточно сильно. А насчет QGraphicsDropShadowEffect, пробовал с такими же параметрами, тени не было вообще, хотя может что то не то задал.


Название: Re: Как сделать подложку текста ?
Отправлено: m_ax от Апрель 05, 2013, 14:59
можно проще:


Название: Re: Как сделать подложку текста ?
Отправлено: Bepec от Апрель 05, 2013, 15:04
Гениально. В очередной раз поражаюсь как люди на форуме умудряются дать полный, обоснованный и понятный любому (не понимающему в программировании) человеку ответ, содержащий максимум информации о проблеме и способах её решения.

PS а как всё просто то!


Название: Re: Как сделать подложку текста ?
Отправлено: m_ax от Апрель 05, 2013, 15:15
Гениально. В очередной раз поражаюсь как люди на форуме умудряются дать полный, обоснованный и понятный любому (не понимающему в программировании) человеку ответ, содержащий максимум информации о проблеме и способах её решения.

PS а как всё просто то!

1372 года я постигал это священное знание у тибетских монахов)
Не зря значит)


Название: Re: Как сделать подложку текста ?
Отправлено: ecspertiza от Апрель 05, 2013, 15:22
m_ax, не совсем понимаю как ты это сделал :) из исходников qml получился вот такой пример

Код:
    QFont font;
    font.setPixelSize(24);
    font.setFamily("Arial");


    int offset = 2;

    QString text = "This is test text";
    QFontMetrics fm(font);

    QPixmap styleSource(fm.width(text),fm.height());
    styleSource.fill(Qt::transparent);
    QPainter paint(&styleSource);
    paint.setPen(Qt::white);
    paint.setBrush(Qt::white);
    paint.setFont(font);
    paint.drawText(1,fm.height(),text);
    paint.end();

    QPixmap source(fm.width(text),fm.height());
    source.fill(Qt::transparent);
    QPainter paint2(&source);
    paint2.setPen(Qt::red);
    paint2.setBrush(Qt::red);
    paint2.setFont(font);
    paint2.drawText(1,fm.height(),text);
    paint2.end();


    QPixmap img = QPixmap(styleSource.width() + offset * 2, styleSource.height() + offset * 2);
    img.fill(Qt::transparent);

    QPainter ppm(&img);

    QPoint pos(0, 0);
    pos += QPoint(-offset, 0);
    ppm.drawPixmap(pos, styleSource);
    pos += QPoint(offset * 2, 0);
    ppm.drawPixmap(pos, styleSource);
    pos += QPoint(-offset, -offset);
    ppm.drawPixmap(pos, styleSource);
    pos += QPoint(0, offset * 2);
    ppm.drawPixmap(pos, styleSource);

    pos += QPoint(0, -offset);
    ppm.drawPixmap(pos, source);
    ppm.end();


    painter->drawPixmap(0,0,img);

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


Название: Re: Как сделать подложку текста ?
Отправлено: m_ax от Апрель 05, 2013, 15:26
m_ax, не совсем понимаю как ты это сделал :) из исходников qml получился вот такой пример

Код:
    QFont font;
    font.setPixelSize(24);
    font.setFamily("Arial");


    int offset = 2;

    QString text = "This is test text";
    QFontMetrics fm(font);

    QPixmap styleSource(fm.width(text),fm.height());
    styleSource.fill(Qt::transparent);
    QPainter paint(&styleSource);
    paint.setPen(Qt::white);
    paint.setBrush(Qt::white);
    paint.setFont(font);
    paint.drawText(1,fm.height(),text);
    paint.end();

    QPixmap source(fm.width(text),fm.height());
    source.fill(Qt::transparent);
    QPainter paint2(&source);
    paint2.setPen(Qt::red);
    paint2.setBrush(Qt::red);
    paint2.setFont(font);
    paint2.drawText(1,fm.height(),text);
    paint2.end();


    QPixmap img = QPixmap(styleSource.width() + offset * 2, styleSource.height() + offset * 2);
    img.fill(Qt::transparent);

    QPainter ppm(&img);

    QPoint pos(0, 0);
    pos += QPoint(-offset, 0);
    ppm.drawPixmap(pos, styleSource);
    pos += QPoint(offset * 2, 0);
    ppm.drawPixmap(pos, styleSource);
    pos += QPoint(-offset, -offset);
    ppm.drawPixmap(pos, styleSource);
    pos += QPoint(0, offset * 2);
    ppm.drawPixmap(pos, styleSource);

    pos += QPoint(0, -offset);
    ppm.drawPixmap(pos, source);
    ppm.end();


    painter->drawPixmap(0,0,img);

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

Да вообщем то, так же и делал.. Сначала фон рисуется со смещением (вверх, вниз, вправо, влево) затем на него по центру рисуется итоговый текст. Можно свой виджет сделать, из QLabel'ов, тогда ещё поддержка html будет.
Я бы веджет свой написал..  


Название: Re: Как сделать подложку текста ?
Отправлено: ecspertiza от Апрель 05, 2013, 15:30
По любому придется писать, ибо еще должна быть возможность редактировать текст.


Название: Re: Как сделать подложку текста ?
Отправлено: _OLEGator_ от Апрель 05, 2013, 15:34
Повторю свой вопрос, на который не ответили:
А просто отрисовка текста с кистью нужной толщины не дает необходимого эффекта? Тоесть когда и заливка и кисть установлена QPainter'у.


Название: Re: Как сделать подложку текста ?
Отправлено: GreatSnake от Апрель 05, 2013, 16:00
А кто мешает просто посмотреть описание QPainterPath::addText() (http://qt-project.org/doc/qt-4.8/qpainterpath.html#addText) ???


Название: Re: Как сделать подложку текста ?
Отправлено: ecspertiza от Апрель 05, 2013, 16:17
_OLEGator_, неа :)


Название: Re: Как сделать подложку текста ?
Отправлено: _OLEGator_ от Апрель 05, 2013, 19:58
to GreatSnake
Это не совсем то, что нужно ТС. Как я понял, необходимо что-то вроде фильтра Outline в фотошопе.

Оно?
Код
C++ (Qt)
QPainter painter(this);
 
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::TextAntialiasing);
painter.translate(50, 80);
 
QPainterPath path;
path.addText(0, 0, QFont("", 20), "Test");
 
painter.setPen(QPen(Qt::gray, 5));
painter.translate(0, 1);
painter.drawPath(path);
painter.translate(0, -1);
 
painter.setPen(QPen(Qt::white, 5));
painter.drawPath(path);
 
painter.fillPath(path, Qt::red);


Название: Re: Как сделать подложку текста ?
Отправлено: ecspertiza от Апрель 19, 2013, 08:13
Случайно эту тему заметил :) _OLEGator_, твой вариант вроде тоже рабочий, я там выше выкладывал рабочий пример. Так же понял почему в qml текст отрисовывают через QPixmap ,а не через QPainterPath, это связанно с тем что QPainterPath не умеет рисовать переносы на следующую строку.


Название: Re: Как сделать подложку текста ?
Отправлено: GreatSnake от Апрель 19, 2013, 09:25
Так же понял почему в qml текст отрисовывают через QPixmap ,а не через QPainterPath, это связанно с тем что QPainterPath не умеет рисовать переносы на следующую строку.
Т.е. QPixmap делает переносы ??? Интересное умозаключение.


Название: Re: Как сделать подложку текста ?
Отправлено: ecspertiza от Апрель 19, 2013, 13:25
Причем тут это  ??? Ты же на QPixmap рисуешь через QPainter, стало быть перенос скорее всего QPainter делает. А QPainterPath насколько понимаю что то вроде вектора, когда ты в него добавляешь что то по ходу он хранит у себя данные о том что нужно отрисовать, стало быть в случае с добавлением текста он его переносить должен. Вот что я хотел сказать:

Если рисуешь текст вот так

Код:
QPainter::drawText(QRect(),"Qt\ndigia");

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