我正在为添加了框架的QGraphicsTextItem设置动画。在动画期间,文本似乎在框架内略微抖动,这很烦人。

示例代码:

class MovingFrameText : public QGraphicsTextItem
{
    Q_OBJECT;

   public:
      MovingFrameText( ) : QGraphicsTextItem(0)
      {
         setPlainText ( "human ");
         QFont f =  font();
         f.setPixelSize(40);
         setFont(f);
         setFlags(QGraphicsItem::ItemIsMovable);
      }

      QRectF boundingRect() const
      {
         return QGraphicsTextItem::boundingRect().adjusted(-2,-2,+2,+2);
      }

      void paint(QPainter *painter,const QStyleOptionGraphicsItem *option,QWidget *widget)
      {
         QGraphicsTextItem::paint(painter,option,widget);
         painter->setPen(Qt::black);
         painter->drawRect(boundingRect());
      }

};

int main(int argc, char *argv[])
{
   QApplication app(argc,argv);


   MovingFrameText t;
   t.setPos(640,680);

   QGraphicsScene scene;
   scene.addItem(&t);

   QGraphicsView view(&scene);
   view.resize(640, 680);
   view.show();

    auto moveAnimation = new QPropertyAnimation( &t,  "pos" );
    moveAnimation->setDuration( 10000 );
    moveAnimation->setStartValue( QPointF(640, 680) );
    moveAnimation->setEndValue(  QPointF(0, 0) );
    moveAnimation->setEasingCurve( QEasingCurve::Linear );
    moveAnimation->start(QAbstractAnimation::DeleteWhenStopped);

 return app.exec();
}

有什么方法可以使动画平滑吗?

最佳答案


您可以通过以下方法大大改善动画效果:

  • 使用 QVariantAnimation 代替QPropertyAnimation并在每次迭代中调用 QGraphicsItem::update
  • 使用附加的QPainterQPixmap作为 Canvas 进行所有绘画操作来缓冲绘画,然后使用传递给paint方法
  • 的绘画工具绘画 Canvas

    注意: QGraphicsTextItem仍然会摇动一点,但是至少它将表现为一个对象,而不是几个独立的对象。

    这是我为您准备的示例,说明如何更改您的代码以实现建议的解决方案:
    class MovingFrameText : public QGraphicsTextItem
    {
    public:
        MovingFrameText(const QString &text, QGraphicsItem *parent = nullptr)
            : QGraphicsTextItem(parent)
        {
            QFont f(font());
    
            f.setPixelSize(40);
    
            setFont(f);
            setPlainText(text);
        }
    
        void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
        {
            painter->setClipping(true);
            painter->setClipRect(option->rect);
            painter->setRenderHint(QPainter::SmoothPixmapTransform);
    
            QPixmap canvas(option->rect.size());
            QPainter canvasPainter;
    
            canvas.fill(Qt::transparent);
    
            canvasPainter.begin(&canvas);
    
            canvasPainter.setFont(font());
            canvasPainter.drawRect(option->rect.adjusted(0, 0, -1, -1));
            canvasPainter.drawText(option->rect, toPlainText());
    
            painter->drawPixmap(0, 0, canvas);
        }
    };
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc,argv);
    
        QGraphicsView view;
        auto *t = new MovingFrameText("human");
    
        view.setScene(new QGraphicsScene(&view));
        view.setAlignment(Qt::AlignLeft | Qt::AlignTop);
        view.setSceneRect(0, 0, 640, 680);
        view.scene()->addItem(t);
        view.show();
    
        auto *moveAnimation = new QVariantAnimation();
    
        moveAnimation->setDuration(10000);
        moveAnimation->setStartValue(QPointF(640, 680));
        moveAnimation->setEndValue(QPointF(0, 0));
        moveAnimation->start(QAbstractAnimation::DeleteWhenStopped);
    
        QObject::connect(moveAnimation, &QVariantAnimation::valueChanged, [t](const QVariant &value){
            t->setPos(value.toPointF());
            t->update();
        });
    
        return app.exec();
    }
    

    07-24 09:28