Skip to content

Commit

Permalink
ImageCarousel
Browse files Browse the repository at this point in the history
  • Loading branch information
RealChuan committed Jul 6, 2023
1 parent 901ddc6 commit 8b9fad0
Show file tree
Hide file tree
Showing 14 changed files with 508 additions and 12 deletions.
14 changes: 9 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
cmake_minimum_required(VERSION 3.16)

project(Qt-Examples VERSION 0.1 LANGUAGES CXX)
project(
Qt-Examples
VERSION 0.1
LANGUAGES CXX)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

IF (CMAKE_HOST_WIN32)
list(APPEND CMAKE_PREFIX_PATH "C:\\Qt\\6.5.0\\msvc2019_64")
ENDIF ()
if(CMAKE_HOST_WIN32)
list(APPEND CMAKE_PREFIX_PATH "C:\\Qt\\6.5.0\\msvc2019_64")
endif()

set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
#qt_standard_project_setup() 这个识别不了
# qt_standard_project_setup() 这个识别不了

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
Expand All @@ -30,6 +33,7 @@ add_subdirectory(DragDrop)
add_subdirectory(FlowLayout)
add_subdirectory(GridViewModel)
add_subdirectory(HttpClient)
add_subdirectory(ImageCarousel)
add_subdirectory(LogAsynchronous)
add_subdirectory(MulClient)
add_subdirectory(MulServer)
Expand Down
14 changes: 7 additions & 7 deletions FlowLayout/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
set(PROJECT_SOURCES
main.cc
mainwindow.cc
mainwindow.hpp
flowlayout.h
flowlayout.cpp
flowwidget.hpp
flowwidget.cc)
main.cc
mainwindow.cc
mainwindow.hpp
flowlayout.h
flowlayout.cpp
flowwidget.hpp
flowwidget.cc)

qt_add_executable(FlowLayout MANUAL_FINALIZATION ${PROJECT_SOURCES})
target_link_libraries(FlowLayout PRIVATE Qt6::Widgets)
Expand Down
12 changes: 12 additions & 0 deletions ImageCarousel/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
set(PROJECT_SOURCES
imagecarousel.cc
imagecarousel.hpp
imagecarouselwidget.hpp
imagecarouselwidget.cc
main.cc
mainwindow.cc
mainwindow.hpp)

qt_add_executable(ImageCarousel MANUAL_FINALIZATION ${PROJECT_SOURCES})
target_link_libraries(ImageCarousel PRIVATE Qt6::Widgets)
qt_finalize_executable(ImageCarousel)
25 changes: 25 additions & 0 deletions ImageCarousel/ImageCarousel.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
QT += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
imagecarousel.cc \
imagecarouselwidget.cc \
main.cc \
mainwindow.cc

HEADERS += \
imagecarousel.hpp \
imagecarouselwidget.hpp \
mainwindow.hpp

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
137 changes: 137 additions & 0 deletions ImageCarousel/imagecarousel.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
#include "imagecarousel.hpp"

#include <QGraphicsPixmapItem>
#include <QTimer>

class ImageCarousel::ImageCarouselPrivate
{
public:
explicit ImageCarouselPrivate(ImageCarousel *q)
: q_ptr(q)
{
timer = new QTimer(q);
timer->setSingleShot(false);
}

ImageCarousel *q_ptr;

QTimer *timer;
int msec = 1000;
int index = 0;
QList<QGraphicsPixmapItem *> items;
};

ImageCarousel::ImageCarousel(QWidget *parent)
: QGraphicsView(parent)
, d_ptr(new ImageCarouselPrivate(this))
{
setScene(new QGraphicsScene(this));
setViewportUpdateMode(SmartViewportUpdate);
setFrameShape(QFrame::NoFrame);
setRenderHint(QPainter::SmoothPixmapTransform);

connect(d_ptr->timer, &QTimer::timeout, this, &ImageCarousel::next);
}

ImageCarousel::~ImageCarousel() = default;

auto ImageCarousel::addImage(const QString &filename) -> bool
{
auto pixmap = QPixmap(filename);
if (pixmap.isNull()) {
return false;
}

auto *item = new QGraphicsPixmapItem(pixmap);
item->setVisible(false);
scene()->addItem(item);
d_ptr->items.append(item);

if (d_ptr->items.count() == 1) {
item->setVisible(true);
}

return true;
}

auto ImageCarousel::addImages(const QStringList &filenames) -> int
{
int count = 0;
for (const auto &filename : qAsConst(filenames)) {
if (addImage(filename)) {
++count;
}
}
return count;
}

void ImageCarousel::clearImages()
{
for (auto item : qAsConst(d_ptr->items)) {
scene()->removeItem(item);
delete item;
}
d_ptr->items.clear();
}

auto ImageCarousel::imageCount() const -> int
{
return d_ptr->items.count();
}

void ImageCarousel::start()
{
d_ptr->timer->start(d_ptr->msec);
}

void ImageCarousel::stop()
{
d_ptr->timer->stop();
}

void ImageCarousel::setInterval(int msec)
{
d_ptr->msec = msec;
}

auto ImageCarousel::interval() const -> int
{
return d_ptr->msec;
}

void ImageCarousel::onImageChanged(int index)
{
Q_ASSERT(index >= 0 && index < d_ptr->items.count());

d_ptr->items[d_ptr->index]->setVisible(false);
d_ptr->index = index;
d_ptr->items[d_ptr->index]->setVisible(true);

resetItem();
}

void ImageCarousel::next()
{
if (d_ptr->items.isEmpty()) {
return;
}

d_ptr->items[d_ptr->index]->setVisible(false);
d_ptr->index = (d_ptr->index + 1) % d_ptr->items.count();
d_ptr->items[d_ptr->index]->setVisible(true);

emit imageChanged(d_ptr->index);

resetItem();
}

void ImageCarousel::resetItem()
{
auto item = d_ptr->items[d_ptr->index];
scene()->setSceneRect(item->boundingRect());
resetTransform();
auto size = item->pixmap().size();
if (size.width() > width() || size.height() > height()) {
fitInView(item, Qt::KeepAspectRatio);
}
}
43 changes: 43 additions & 0 deletions ImageCarousel/imagecarousel.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#ifndef IMAGECAROUSEL_HPP
#define IMAGECAROUSEL_HPP

// qt image carousel control class

#include <QGraphicsView>

class ImageCarousel : public QGraphicsView
{
Q_OBJECT
public:
explicit ImageCarousel(QWidget *parent = nullptr);
~ImageCarousel() override;

auto addImage(const QString &filename) -> bool;
auto addImages(const QStringList &filenames) -> int;
void clearImages();

[[nodiscard]] auto imageCount() const -> int;

void start();
void stop();

void setInterval(int msec);
[[nodiscard]] auto interval() const -> int;

public slots:
void onImageChanged(int index);

signals:
void imageChanged(int index);

private slots:
void next();

private:
void resetItem();

class ImageCarouselPrivate;
QScopedPointer<ImageCarouselPrivate> d_ptr;
};

#endif // IMAGECAROUSEL_HPP
120 changes: 120 additions & 0 deletions ImageCarousel/imagecarouselwidget.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#include "imagecarouselwidget.hpp"
#include "imagecarousel.hpp"

#include <QtWidgets>

class ImageCarouselWidget::ImageCarouselWidgetPrivate
{
public:
ImageCarouselWidgetPrivate(ImageCarouselWidget *q)
: q_ptr{q}
{
carousel = new ImageCarousel{q};
btnGroup = new QButtonGroup{q};
btnGroup->setExclusive(true);
layout = new QVBoxLayout{q};

layout->addWidget(carousel);
}
~ImageCarouselWidgetPrivate() = default;

void resetBtnWidget()
{
auto btns = btnGroup->buttons();
for (auto btn : btns) {
btnGroup->removeButton(btn);
delete btn;
}
if (!btnWidget.isNull()) {
delete btnWidget.data();
}
btnWidget = new QWidget(q_ptr);
layout->addWidget(btnWidget.data());
auto btnLayout = new QHBoxLayout{btnWidget.data()};
btnLayout->addStretch();
auto count = carousel->imageCount();
for (auto i = 0; i < count; ++i) {
auto btn = new QRadioButton{btnWidget.data()};
btnLayout->addWidget(btn);
btnGroup->addButton(btn, i);
}
btnLayout->addStretch();
}

ImageCarouselWidget *q_ptr;

ImageCarousel *carousel;
QPointer<QWidget> btnWidget;
QButtonGroup *btnGroup;
QVBoxLayout *layout;
};

ImageCarouselWidget::ImageCarouselWidget(QWidget *parent)
: QWidget{parent}
, d_ptr{new ImageCarouselWidgetPrivate{this}}
{
buildConnect();
}

ImageCarouselWidget::~ImageCarouselWidget() = default;

void ImageCarouselWidget::addImage(const QString &filename)
{
d_ptr->carousel->addImage(filename);

d_ptr->resetBtnWidget();
}

void ImageCarouselWidget::addImages(const QStringList &filenames)
{
d_ptr->carousel->addImages(filenames);

d_ptr->resetBtnWidget();
}

void ImageCarouselWidget::clearImages()
{
d_ptr->carousel->clearImages();

d_ptr->resetBtnWidget();
}

void ImageCarouselWidget::start()
{
d_ptr->carousel->start();
}

void ImageCarouselWidget::stop()
{
d_ptr->carousel->stop();
}

void ImageCarouselWidget::setInterval(int msec)
{
d_ptr->carousel->setInterval(msec);
}

auto ImageCarouselWidget::interval() const -> int
{
return d_ptr->carousel->interval();
}

void ImageCarouselWidget::onImageChanged(int index)
{
auto btn = d_ptr->btnGroup->button(index);
if (btn) {
btn->setChecked(true);
}
}

void ImageCarouselWidget::buildConnect()
{
connect(d_ptr->carousel,
&ImageCarousel::imageChanged,
this,
&ImageCarouselWidget::onImageChanged);
connect(d_ptr->btnGroup,
&QButtonGroup::idClicked,
d_ptr->carousel,
&ImageCarousel::onImageChanged);
}
Loading

0 comments on commit 8b9fad0

Please sign in to comment.