【Technology Sharing】Calendar-Interface Animation Switching

Deepin
3 min readApr 29, 2022

--

Calendar (dde-calendar) is a calendar tool pre-installed by deepin. Its main functions include displaying the current date, solar terms, lunar calendar, and managing schedule information. The calendar currently has four views: year view, month view, week view and day view. Individual views are placed on the stack window QStackedWidget.

In order to improve the user experience and solve the problem that the built-in QStackedWidget does not have the effect of animation switching, the calendar developed based on Qt uses QPropertyAnimation and QPainter to enable QStackedWidget to support the effect of animation switching.

Next, this article will introduce the process of animation switching based on QStackedWidget for each view of the calendar application from the perspective of technical implementation.

1. Technical Background

  • QStackedWidget is a stack window, you can jump or get the corresponding window by index.
QWidget *QStackedWidget::widget(int index) const
//Get the window at the index index position
QWidget *QStackedWidget::currentWidget() const
// get the current window
void QStackedWidget::setCurrentIndex(int index)
//Set the window at the index index position as the current window
  • QPaint can paint on canvas.
void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
/ / Draw the source part of the pixmap on the target position of the canvas

2. Implementation principle

QStackedWidget switch window is to jump directly to the corresponding window. For example, now there are Y, M, W and D windows, switching from the Y window to the W window, Qt’s default QStackedWidget is to jump directly from the Y window to the W window:

In order to make QStackedWidget support the animation switching effect, hide window Y before QStackedWidget jumps from window Y to window W, obtain the pictures of window Y and window W, then enable the QPropertyAnimation property animation, update the drawing window Y and window W, and at the end of the animation Then switch to window W, so as to achieve the effect of animation switching window:

Window Y picture drawing animation process is as follows:

Window W picture drawing animation process is as follows:

3. Coding implementation

According to the above process, part of the implementation code is as follows:

Set the current window according to the index, start animation drawing

void AnimationStackedWidget::setCurrentWidget(int &index, int beginWidth)
{
//If animation is in progress, then exit
if (m_IsAnimation) {
return;
}
//Exit if the index is the current index
if (index == currentIndex()) {
emit signalIsFinished();
return;
}
m_IsAnimation = true;
m_NextIndex = index;
//Get the picture of the current window
QPixmap currentPixmap(this->size());
currentWidget()->render(&currentPixmap);
m_currentPixmap = currentPixmap;
//Get the picture that needs to jump to the window
QPixmap nextPixmap(this->size());
QWidget *nextWidget = widget(index);
nextWidget->resize(this->size().width(),this->size().height());
nextWidget->render(&nextPixmap);
m_nextPixmap = nextPixmap;
//Hide the current widget
this->widget(currentIndex())->hide();
m_Animation->setStartValue(beginWidth);
m_Animation->setEndValue(0);
m_Animation->setDuration(m_Duration);
m_Animation->start();
}

draw current window

void AnimationStackedWidget::paintCurrentWidget(QPainter &paint)
{
QRect widgetRect = this->rect();
//Draw the current Widget
double value = m_offset;
//window width
const int widgetWidth = widgetRect.width();
//window height
const int widgetHeight = widgetRect.height();
QRectF targetRect;
QRectF sourceRect;
targetRect = QRectF(0.0, 0.0, value, widgetHeight);
sourceRect = QRectF(widgetWidth - value, 0, value, widgetHeight);
paint.drawPixmap(targetRect, m_currentPixmap, sourceRect);
}

Draw the window to jump to

void AnimationStackedWidget::paintNextWidget(QPainter &paint)
{
QRect widgetRect = this->rect();
double value = m_offset;
//window width
const int widgetWidth = widgetRect.width();
//window height
const int widgetHeight = widgetRect.height();
QRectF targetRect;
QRectF sourceRect;
targetRect = QRectF(value, 0.0, widgetWidth - value, widgetHeight);
sourceRect = QRectF(0.0, 0.0, widgetWidth - value, widgetHeight);
paint.drawPixmap(targetRect,m_nextPixmap,sourceRect);
}

The above is the introduction of the animation switching window technology based on the QStackedWidget control for the calendar application.

--

--