PDA

View Full Version : Smooth text scrolling



francesco.frankie
26th November 2010, 22:55
Hello!
I'm writing a program that should render the text embedded in a QTextDocument on a QGraphicsView, the text must be scaled and smoothly scrolled.
To do this job I've inherited the class QGraphicsItem and implemented the funciont paint, after the item is added to a QGraphicsScene that calls the function advance() every 30 milliseconds.

here is the code of the paint function:




void ScrollTextGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){

if(currentDocument){

painter->setRenderHint(QPainter::SmoothPixmapTransform);

painter->translate(0,-scrollValue);

painter->scale(renderScale.width(),renderScale.height());

QAbstractTextDocumentLayout::PaintContext pcontext;
pcontext.palette.setColor(QPalette::Text, scrollScene->getDefaultTextColor());

pcontext.clip = QRectF(0,scrollValue/renderScale.height(),
renderSize.width()/renderScale.width(),
renderSize.height()/renderScale.height());

currentDocument->documentLayout()->draw(painter,pcontext);

}
}



The matter is if the result is almost reasonable for light-weight documents and for low scale factor, the performances turn down even for a small portion of text (few lines) scaled and drawn in a window 800x600.
Did i forget some optimization? Are there ways for improve the draw algorithm (for example using a QGLWidget)?
Have you some hints or suggestions?


thanks for the attention
Regards

wysota
27th November 2010, 02:13
Is there a reason why you didn't use QGraphicsTextItem?

francesco.frankie
27th November 2010, 19:35
Thank you for your reply.
Yes, I've tried it, but the performance problem persist.
Do you have other advices?

wysota
27th November 2010, 19:39
What is the performance problem? Please provide an example.

francesco.frankie
28th November 2010, 11:32
OK, I've made some test. Although the CPU level is low, the scroll animation isn't smooth, indeed depends on the resolution of the window where the scene is placed. I think the matter is resize and scale the scene...
For the animation I connect a timeout event of a timer with the function "advance" of the scene. The painter of the graphics item is moved by a number of pixel depends on the time elapsed sine last drawing.

tbscope
28th November 2010, 13:07
That's still not an example.

Here are a few:
http://doc.qt.nokia.com/4.7/examples-animation.html

I made a little test with a graphicsview and a qgraphicsproxywidget containing a label and using qpropertyanimation. The animation is smooth.

francesco.frankie
28th November 2010, 22:23
thank you guys for the attention and the support, and sorry if i wasn't able to provide a clear question.
My program should scroll in a full screen window a very large QTextDocument, about 5 lines in the same moment. I've tried several ways to perform the animation and render the text, but I wasn't able to obtain a real smooth and flicker-free animation.
In your opinion, which is the best way to do that? I followed the Animation tutorial and read articles about QT Graphics View Framework, but I didn't find the answer.

wysota
29th November 2010, 00:36
Why don't you just write a short (up to 30 lines of code) example demonstrating the problem?

francesco.frankie
29th November 2010, 22:32
Why don't you just write a short (up to 30 lines of code) example demonstrating the problem?

Well, here is a quick example about what i told.
I made a main window with a QTextEdit and a PushButton, let's try to copy and paste some text and click "start"
In this case I used a QGraphicsTextItem (as suggested by wysota) a timer and the "translate" method to arrange the scrolling.
The result (at least on my computer) flickers and isn't smooth.
Ok, this is a real simple example, but starting from this code, how can i improve the results?
Or...should I chose a totally different way?



//file: mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtGui/QApplication>
#include <QMainWindow>
#include <QGraphicsTextItem>
#include <QPushButton>
#include <QTextEdit>
#include <QGraphicsView>
#include <QGraphicsTextItem>
#include <QTimeLine>
#include <QTimer>
#include <QTime>
#include <QRect>
#include <QPushButton>
#include <QVBoxLayout>

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0) : QMainWindow(parent){
QVBoxLayout* layout = new QVBoxLayout();

pushButton = new QPushButton("start");
textEdit = new QTextEdit();
layout->addWidget(textEdit);
layout->addWidget(pushButton);
QWidget* central = new QWidget();
central->setLayout(layout);
setCentralWidget(central);
connect(pushButton, SIGNAL(clicked()),SLOT(start()));
}

~MainWindow(){

}

QGraphicsView* view;
QGraphicsTextItem * text ;
QGraphicsScene* scene;
QPushButton* pushButton;
QTextEdit* textEdit;
QTime* timeSinceLastUpdate;


public slots:

void start(){
scene = new QGraphicsScene();
text = new QGraphicsTextItem();
text->setDocument(textEdit->document());
text->scale(6,6);
text->setPos(-100,0);
text->setTextWidth(140);

scene->addItem(text);
scene->setSceneRect(0,0,400,400);
view = new QGraphicsView(scene);
view->fitInView(view->sceneRect(),Qt::KeepAspectRatio);
view->setRenderHint(QPainter::SmoothPixmapTransform);
view->showFullScreen();

QTimer* sctT = new QTimer();
connect(sctT,SIGNAL(timeout()),SLOT(scroll()));

sctT->start(30);

timeSinceLastUpdate = new QTime();
timeSinceLastUpdate->start();
}

void scroll(){
int time = timeSinceLastUpdate->elapsed(); //make the scrolling indipendent from frame rate
float scrollValue = (40.0 * float(time))/1000.0;
text->translate(0,-scrollValue);
timeSinceLastUpdate->restart();

}
};




#endif // MAINWINDOW_H

file: main.cpp

#include <QtGui/QApplication>

#include "mainwindow.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

return a.exec();
}




Thank for the support!

wysota
29th November 2010, 23:16
The animation is fluent on my machine but you can try this:



#include <QtGui>

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0) : QMainWindow(parent){
QVBoxLayout* layout = new QVBoxLayout();

pushButton = new QPushButton("start");
textEdit = new QTextEdit();
layout->addWidget(textEdit);
layout->addWidget(pushButton);
QWidget* central = new QWidget();
central->setLayout(layout);
setCentralWidget(central);
connect(pushButton, SIGNAL(clicked()),SLOT(start()));
}

QGraphicsView* view;
QGraphicsTextItem * text ;
QGraphicsScene* scene;
QPushButton* pushButton;
QTextEdit* textEdit;

public slots:

void start(){
scene = new QGraphicsScene();
text = new QGraphicsTextItem();
text->setDocument(textEdit->document());
text->scale(6,6);
text->setPos(-100,0);
text->setTextWidth(140);

scene->addItem(text);
scene->setSceneRect(0,0,400,400);
view = new QGraphicsView(scene);
view->fitInView(view->sceneRect(),Qt::KeepAspectRatio);
view->setRenderHint(QPainter::SmoothPixmapTransform);
view->showFullScreen();

// the important part:
QPropertyAnimation *anim = new QPropertyAnimation(text, "pos", text);
anim->setStartValue(text->pos());
anim->setEndValue(QPointF(-100, -1000));
anim->setDuration(5000);
anim->start();
}
};

#include "main.moc"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

return a.exec();
}