Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: gil9red от Ноябрь 06, 2014, 09:42



Название: [РЕШЕНО] Реализация простого ткстового QGraphicsItem
Отправлено: gil9red от Ноябрь 06, 2014, 09:42
Когда уменьшается количество символов в тексте и происходит перерисовка элемента, кусок предыдущего текста остается. Т.е. рисуется новый текст поверх старого.
Пропает сей артефакт при клике на сцену.

Сам класс:
Код
Java
class TextDesignItem extends QGraphicsItem {
   public TextDesignItem() {
       super();
   }
 
   private String text = new String();
   public void setText(String t) {
       text = t;
       update();
   }
   public String getText() {
       return text;
   }
 
   private QFont font = new QFont();
   public void setFont(QFont f) {
       font = f;
       update();
   }
   public QFont getFont() {
       return font;
   }
 
   @Override
   public QRectF boundingRect() {
       QFontMetricsF fm = new QFontMetricsF(font);
       QRectF rect = fm.boundingRect(text);
       rect.moveTo(0, 0);
       return rect;
   }
 
   @Override
   public void paint(QPainter painter, QStyleOptionGraphicsItem option, QWidget widget) {
       painter.setRenderHint(QPainter.RenderHint.HighQualityAntialiasing, true);
       painter.setFont(font);
       QRectF rect = boundingRect();
       // Добавил 5.0, т.к. текст может не поместиться в rect, и тогда будет обрезан
       rect.setWidth(rect.width() + 5.0);
       painter.drawText(rect, text);
 
       // Нарисуем рамку вокруг элемента
       if (isSelected())
           qt_graphicsItem_highlightSelected(this, painter, option);
   }
}
 

Тыкните в чем проблема, спасибо :)


Название: Re: Реализация простого текстового QGraphicsItem
Отправлено: Fregloin от Ноябрь 06, 2014, 12:40
все просто, нужно при изменении текста вызывать prepareGeometryChange().

вот мой код для примера
Код:
void YourTextItem::setText(const QString & text)
{
 if(p_text!=text)
{
 prepareGeometryChange();
 p_text = text;
}
}

но нужно также переопределить boundingRect() в котором у вас должен возвращаться QRectF который занимается текстом на сцене. Могу посоветовать делать через QFontMetrics.


Название: Re: Реализация простого текстового QGraphicsItem
Отправлено: Fregloin от Ноябрь 06, 2014, 12:52
если в двух словах, при любом предполагаем изменении размеров элемента на сцене следует вызывать метод prepareGeometryChange() вместо update(), так как update просто заставляет перерисовать сцену элемент со старыми размерами (видать есть какое то кеширование), а prepareGeometryChange говорит сцене, что размер элемента будет меняться, и она дернет все нужные функции для того что бы сцена обновила размер элемента у себя в кеше и перерисовала уже без артефактов. ну и желательно boundingRect вызывать с adjusted(-1,-1,1,1).
Еще может влиять параметр QGraphicsView::setViewportUpdateMode(QGraphicsView::FullViewportUpdate); который заставляет перерисовывать сцену полностью при любых изменениях элементов.
Вроде как щас в любом случае рисуется через OpenGL(начиная с Qt5.0), то этот параметр более целесообразен чем другие.


Название: Re: Реализация простого текстового QGraphicsItem
Отправлено: gil9red от Ноябрь 06, 2014, 13:51
Fregloin, boundingRect() переопределен, что видно в коде, который приложил :)
Заменил update на prepareGeometryChange и все стало правильно перерисовываться, спасибо :)