#include <QtGui>
{
Q_OBJECT
public:
virtual void setDuration(int duration) { m_duration = duration; }
virtual int duration() const { return m_duration; }
virtual void setWidget
(QWidget* widget
) { m_widget
= widget;
} virtual QWidget* widget
() const { return m_widget;
}
private:
int m_duration;
};
class TestTransition : public Transition
{
Q_OBJECT
public:
TestTransition
(QWidget* parent
= 0) : Transition
(parent
) { connect(m_timeLine, SIGNAL(valueChanged(qreal)),
this, SLOT(onValueChanged(qreal)));
connect(m_timeLine, SIGNAL(finished()),
this, SLOT(onFinished()));
hide();
}
void setDuration(int duration) {
Transition::setDuration(duration);
m_timeLine->setDuration(this->duration());
}
resize(widget()->size());
// Grab Images
m_beforeImage
= QPixmap::grabWidget(before
).
toImage();
// Set foreground brush
m_afterImage = mp.toImage();
m_finalImage = m_beforeImage;
int side = qMax(width(), height());
m_radius
= (rect
().
center() + QPoint(side
/2, side
/2)).
manhattanLength();
m_timeLine->start();
show();
}
p.drawImage(0, 0, m_finalImage);
}
private:
int m_radius;
private slots:
void onValueChanged(qreal value) {
p.
setRenderHints(QPainter::Antialiasing);
p.setPen(Qt::gray);
p.setBrush(m_fgBrush);
const int r = (int)(m_radius * value);
p.drawEllipse(rect().center(), r, r);
update();
}
void onFinished() {
hide();
}
};
{
Q_OBJECT
public:
// Layout
m_layout->addWidget(w);
m_layout->addWidget(t);
// Central Widget
cw->setLayout(m_layout);
setCentralWidget(cw);
// Transition
m_transition = new TestTransition(this);
m_transition->setWidget(cw);
m_transition->setDuration(400);
act->setShortcut(tr("Ctrl+A"));
connect(act, SIGNAL(triggered()), this, SLOT(changePage()));
addAction(act);
}
private:
TestTransition* m_transition;
private slots:
void changePage() {
int index = m_layout->currentIndex();
index == 1 ? --index : ++index;
// Transition
m_transition->startTransition(m_layout->widget(m_layout->currentIndex()),
m_layout->widget(index));
m_layout->setCurrentIndex(index);
}
};
int main(int argc, char** argv)
{
MainWindow mw;
mw.show();
return app.exec();
}
#include "main.moc"
#include <QtGui>
class Transition : public QWidget
{
Q_OBJECT
public:
Transition(QWidget* parent = 0) : QWidget(parent){};
virtual void setDuration(int duration) { m_duration = duration; }
virtual int duration() const { return m_duration; }
virtual void setWidget(QWidget* widget) { m_widget = widget; }
virtual QWidget* widget() const { return m_widget; }
virtual void startTransition(QWidget* before, QWidget* after) = 0;
private:
QWidget* m_widget;
int m_duration;
};
class TestTransition : public Transition
{
Q_OBJECT
public:
TestTransition(QWidget* parent = 0) : Transition(parent) {
m_timeLine = new QTimeLine(333, this);
connect(m_timeLine, SIGNAL(valueChanged(qreal)),
this, SLOT(onValueChanged(qreal)));
connect(m_timeLine, SIGNAL(finished()),
this, SLOT(onFinished()));
hide();
}
void setDuration(int duration) {
Transition::setDuration(duration);
m_timeLine->setDuration(this->duration());
}
void startTransition(QWidget* before, QWidget* after) {
resize(widget()->size());
// Grab Images
m_beforeImage = QPixmap::grabWidget(before).toImage();
QPixmap mp = QPixmap::grabWidget(after);
// Set foreground brush
m_fgBrush = QBrush(mp);
m_afterImage = mp.toImage();
m_finalImage = m_beforeImage;
int side = qMax(width(), height());
m_radius = (rect().center() + QPoint(side/2, side/2)).manhattanLength();
m_timeLine->start();
show();
}
void paintEvent(QPaintEvent* event) {
QPainter p(this);
p.drawImage(0, 0, m_finalImage);
}
private:
QTimeLine* m_timeLine;
QImage m_beforeImage;
QImage m_afterImage;
QImage m_finalImage;
QBrush m_fgBrush;
int m_radius;
private slots:
void onValueChanged(qreal value) {
QPainter p(&m_finalImage);
p.setRenderHints(QPainter::Antialiasing);
p.setPen(Qt::gray);
p.setBrush(m_fgBrush);
const int r = (int)(m_radius * value);
p.drawEllipse(rect().center(), r, r);
update();
}
void onFinished() {
hide();
}
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget* parent = 0) : QMainWindow(parent) {
QCalendarWidget* w = new QCalendarWidget;
QTextEdit* t = new QTextEdit;
// Layout
m_layout = new QStackedLayout;
m_layout->addWidget(w);
m_layout->addWidget(t);
// Central Widget
QWidget* cw = new QWidget;
cw->setLayout(m_layout);
setCentralWidget(cw);
// Transition
m_transition = new TestTransition(this);
m_transition->setWidget(cw);
m_transition->setDuration(400);
QAction* act = new QAction(this);
act->setShortcut(tr("Ctrl+A"));
connect(act, SIGNAL(triggered()), this, SLOT(changePage()));
addAction(act);
}
private:
QStackedLayout* m_layout;
TestTransition* m_transition;
private slots:
void changePage() {
int index = m_layout->currentIndex();
index == 1 ? --index : ++index;
// Transition
m_transition->startTransition(m_layout->widget(m_layout->currentIndex()),
m_layout->widget(index));
m_layout->setCurrentIndex(index);
}
};
int main(int argc, char** argv)
{
QApplication app(argc, argv);
MainWindow mw;
mw.show();
return app.exec();
}
#include "main.moc"
To copy to clipboard, switch view to plain text mode
executing the animation by pressing ctrl + A, resizing the widget and starting the animation again will show the problem. It is solved if setCurrentIndex() is called before the animation starts. I don't have access to the fixed version right now (I'll post it tomorrow) but that doesn't change the problem that QPixmap::grabWidget() seems to return a pixmap that reflects the state of the widget before it was hidden and doesn't seem to repaint itself in reponse to render() or grabWidget().
Bookmarks