#c #qt
#c #qt
Вопрос:
Моя цель
Я хочу анимировать изображения в слайд-шоу следующим образом:
<< Animation Direction <<
/* THIS IS EXPECTATION */
--------------------
--------------------
CURR IMAGE ------ NEXT IMAGE --
--------------------
--------------------
<--- VIEW --------->
--------------------
--------------------
IMAGE ------ NEXT IMAGE --
--------------------
--------------------
<--- VIEW --------->
--------------------
--------------------
------ NEXT IMAGE --
--------------------
--------------------
<--- VIEW --------->
Что я пробовал
Я использую два экземпляра QPropertyAnimation
:
d->currImage = new QLabel(ui->frmSlideshow);
d->currImage->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
d->animCurrImage = new QPropertyAnimation(d->currImage, "geometry");
d->nextImage = new QLabel(ui->frmSlideshow);
d->nextImage->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
d->animNextImage = new QPropertyAnimation(d->nextImage, "geometry");
connect(d->animNextImage, SIGNAL(finished()),this, SLOT(applyBackground()));
connect(amp;(d->timer), SIGNAL(timeout()), this, SLOT(timer_timeout()));
d->timer.start(1500);
По истечении времени ожидания я делаю следующее:
QPixmap pixCurrImage;
pixCurrImage.load(d->currImagePath());
d->currImage->setPixmap(pixCurrImage);
QPixmap pixNextImage;
pixNextImage.load(d->nextImagePath());
d->nextImage->setPixmap(pixNextImage);
d->currImage->show();
d->currImage->raise();
d->currImage->setFixedSize(ui->frmSlideshow->size());
d->nextImage->show();
d->nextImage->raise();
d->nextImage->setFixedSize(ui->frmSlideshow->size());
d->animCurrImage->setDuration(500);
d->animCurrImage->setStartValue(QRect(0, 0, ui->frmSlideshow->width(), ui->frmSlideshow->height()));
d->animCurrImage->setEndValue(QRect(-1*ui->frmSlideshow->width(), 0, ui->frmSlideshow->width(), ui->frmSlideshow->height()));
d->animNextImage->setDuration(500);
d->animNextImage->setStartValue(QRect(2*ui->frmSlideshow->width(), 0, ui->frmSlideshow->width(), ui->frmSlideshow->height()));
d->animNextImage->setEndValue(QRect(0, 0, ui->frmSlideshow->width(), ui->frmSlideshow->height()));
QParallelAnimationGroup * group = new QParallelAnimationGroup(this);
group->addAnimation(d->animCurrImage);
group->addAnimation(d->animNextImage);
group->start();
Моя проблема
Между обоими скользящими изображениями отображается небольшой разрыв (около 100 пикселей):
<< Animation Direction <<
/* THIS IS HAPPENING*/
--------------------
--------------------
IMAGE ------ NEXT IMAGE --
--------------------
--------------------
<--- VIEW --------->
--------------------
--------------------
------ NEXT IMAGE --
--------------------
--------------------
<--- VIEW --------->
--------------------
--------------------
------ NEXT IMAGE --
--------------------
--------------------
<--- VIEW --------->
Как заставить его либо работать должным образом, либо достичь желаемой анимации каким-либо другим способом?
Комментарии:
1. Взгляните на
SlideView
класс моей библиотеки FlatGUI и либо используйте его как есть, либо адаптируйте к своим потребностям.
Ответ №1:
Для достижения желаемой анимации я предлагаю вам взглянуть на HorizontalSlide
класс FlatGUI
библиотеки виджетов, написанный мной.
Там я использую QVariantAnimation
для создания эффекта скольжения. Вот основные части HorizontalSlide
, касающиеся анимации:
void HorizontalSlide::start(bool slideLeft, int speed)
{
QVariantAnimation *animation = new QVariantAnimation(this);
m_slideLeft = slideLeft;
m_labCurrent->show();
m_labNext->show();
animation->setStartValue(m_slideLeft ? 0 : m_width);
animation->setEndValue(m_slideLeft ? m_width : 0);
animation->setDuration(speed);
animation->start(QVariantAnimation::DeleteWhenStopped);
connect(animation, amp;QVariantAnimation::valueChanged,
this, amp;HorizontalSlide::onValueChanged);
connect(animation, amp;QVariantAnimation::finished,
this, amp;HorizontalSlide::onAnimationFinished);
}
void HorizontalSlide::onValueChanged(const QVariant amp;value)
{
int n = -value.toInt(), m = m_width n;
if (m_slideLeft) {
m_labCurrent->move(n, 0);
m_labNext->move(m, 0);
} else {
m_labCurrent->move(m, 0);
m_labNext->move(n, 0);
}
m_parentWidget->repaint();
}
void HorizontalSlide::onAnimationFinished()
{
delete m_labCurrent;
delete m_labNext;
m_nextPage->show();
m_nextPage->resize(m_parentWidget->size());
deleteLater();
finished();
}
Я использую QVariantAnimation::valueChanged
сигнал для QWidget::move
моментального снимка виджетов, чтобы скользить по оси x
-. Затем код реагирует на QAbstractAnimation::finished
сигнал на QWidget::show
и QWidget::resize
на следующую страницу.
При условии, что у вас есть эти переменные, объявленные и инициализированные:
QWidgetList pages;
currentIndex(-1),
nextIndex(-1),
busy(false)
вы могли бы использовать HorizontalSlide
в методе, подобном этому:
void slideToPage(int n, int speed) {
if (busy
|| pages.isEmpty()
|| (currentIndex < 0)
|| (n == currentIndex)
|| (speed < 0))
return;
auto *transition = new HorizontalSlide(this);
busy = true;
transition->setCurrentPage(pages.at(currentIndex));
transition->setNextPage(pages.at(n));
transition->start(n > currentIndex, speed);
connect(transition, amp;HorizontalSlide::finished,
[this, transition](){
currentIndex = pages.indexOf(transition->nextPage());
busy = false;
currentIndexChanged(currentIndex, pages.count());
currentPageChanged(pages.at(currentIndex)->windowTitle());
});
}
Вы также можете добавить библиотеку в свой проект и использовать ее SlideView
класс.
Комментарии:
1. Спасибо, это было небольшое задание. Поэтому я не включил всю библиотеку
2. @Jai, моего комментария, как вы подтвердили, было достаточно, чтобы помочь вам. Однако для дальнейшего использования необходим более полный ответ, поэтому я также предоставил его.
3. Конечно, спасибо 🙂
Ответ №2:
ЗАГРУЗКА ИЗОБРАЖЕНИЙ
d->currImage->setFixedSize(ui->frmSlideshow->size());
d->currImage->move(0,0);
QPixmap pixCurrImage;
pixCurrImage.load(d->currImagePath());
d->currImage->setPixmap(pixCurrImage);
d->currImage->show();
d->currImage->raise();
d->nextImage->setFixedSize(ui->frmSlideshow->size());
d->nextImage->move(ui->frmSlideshow->width(), 0); // So that
QPixmap pixNextImage; // you will not see
pixNextImage.load(d->nextImagePath()); // glitch due
d->nextImage->setPixmap(pixNextImage); // to change
d->nextImage->show();
d->nextImage->raise();
Анимация (спасибо пользователю 6528273 за помощь)
QVariantAnimation *animation = new QVariantAnimation(ui->frmSlideshow);
animation->setStartValue(0);
animation->setEndValue(ui->frmSlideshow->width());
animation->setDuration(600);
animation->start(QVariantAnimation::DeleteWhenStopped);
connect(animation, SIGNAL(valueChanged(QVariant)),
this, SLOT(onValueChanged(QVariant)));
СЛОТ — OnValueChanged()
void onValueChanged(const QVariant amp;value)
{
int n = -value.toInt();
int m = ui->frmSlideshow->width() n;
d->currImage->move(n, 0);
d->nextImage->move(m, 0);
this->repaint();
}
/** ui->frmSlideshow is the frame, on which images are sliding **/