diff --git a/netfriend/0snap/astackwidget.jpg b/netfriend/0snap/astackwidget.jpg new file mode 100644 index 0000000..e8c5edd Binary files /dev/null and b/netfriend/0snap/astackwidget.jpg differ diff --git a/netfriend/0snap/imagecropper.jpg b/netfriend/0snap/imagecropper.jpg new file mode 100644 index 0000000..d02430e Binary files /dev/null and b/netfriend/0snap/imagecropper.jpg differ diff --git a/netfriend/0snap/imageviewwindow.jpg b/netfriend/0snap/imageviewwindow.jpg new file mode 100644 index 0000000..b5fcfa8 Binary files /dev/null and b/netfriend/0snap/imageviewwindow.jpg differ diff --git a/netfriend/0snap/sliderpuzzlewidget.jpg b/netfriend/0snap/sliderpuzzlewidget.jpg new file mode 100644 index 0000000..1fc84e1 Binary files /dev/null and b/netfriend/0snap/sliderpuzzlewidget.jpg differ diff --git a/netfriend/astackwidget/astackwidget.cpp b/netfriend/astackwidget/astackwidget.cpp new file mode 100644 index 0000000..dce0220 --- /dev/null +++ b/netfriend/astackwidget/astackwidget.cpp @@ -0,0 +1,172 @@ +#include "astackwidget.h" + +#include +#include + +AStackWidget::AStackWidget(QWidget *parent) + : QWidget(parent) +{ + m_offset = 0; + m_curIndex = 0; + m_lastIndex = 0; + m_duration = 500; + m_moveAnimation = new QPropertyAnimation(this, ""); + m_moveAnimation->setDuration(m_duration); + connect(m_moveAnimation, &QPropertyAnimation::valueChanged, this, &AStackWidget::onValueChanged); + connect(m_moveAnimation, &QPropertyAnimation::finished, this, &AStackWidget::onMoveFinished); +} + +AStackWidget::~AStackWidget() +{ + +} + +int AStackWidget::count() const +{ + return m_widgetLst.size(); +} + +int AStackWidget::currentIndex() const +{ + return m_curIndex; +} + +void AStackWidget::setDuration(int duration) +{ + m_duration = duration; +} + +int AStackWidget::addWidget(QWidget * widget) +{ + int index = indexOf(widget); + if (index >= 0){ + return index; + } + widget->setParent(this); + m_widgetLst.append(widget); + return count() - 1; +} + +int AStackWidget::indexOf(QWidget * widget) const +{ + return m_widgetLst.indexOf(widget); +} + +int AStackWidget::insertWidget(int index, QWidget * widget) +{ + int curindex = indexOf(widget); + if (curindex >= 0) { + return curindex; + } + widget->setParent(this); + m_widgetLst.insert(index, widget); + return index; +} + +QWidget * AStackWidget::currentWidget() const +{ + if (m_curIndex >= 0 && m_curIndex < count()){ + return m_widgetLst.at(m_curIndex); + } + return 0; +} + +QWidget * AStackWidget::widget(int index) const +{ + if (index >= 0 && index < count()) { + return m_widgetLst.at(index); + } + return 0; +} + +void AStackWidget::removeWidget(QWidget * widget) +{ + int index = indexOf(widget); + if (index >= 0) { + m_widgetLst.removeAll(widget); + emit widgetRemoved(index); + } +} + +void AStackWidget::setCurrentWidget(QWidget * widget) +{ + int index = indexOf(widget); + if (index >= 0 && m_curIndex != index) { + setCurrentIndex(index); + } +} + +void AStackWidget::setCurrentIndex(int index) +{ + if (index >= 0 && m_curIndex != index) { + m_lastIndex = m_curIndex; + m_curIndex = index; + moveAnimationStart(); + emit currentChanged(index); + } +} + +void AStackWidget::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); + + int size = count(); + for (int i = 0; i < size; i++) { + m_widgetLst.at(i)->resize(this->width(), this->height()); + } + + if (m_moveAnimation->state() == QAbstractAnimation::Running) { + moveAnimationStart(); + } + else { + setWidgetsVisible(); + onValueChanged(0); + } +} + +void AStackWidget::onValueChanged(const QVariant &value) +{ + m_offset = value.toInt(); + m_widgetLst.at(m_curIndex)->move(m_offset, 0); + if (m_curIndex > m_lastIndex) { + m_widgetLst.at(m_lastIndex)->move(m_offset - this->width(), 0); + } else if (m_curIndex < m_lastIndex){ + m_widgetLst.at(m_lastIndex)->move(this->width() + m_offset, 0); + } +} + +void AStackWidget::moveAnimationStart() +{ + m_moveAnimation->stop(); + setWidgetsVisible(); + int startOffset = m_offset; + if (m_curIndex > m_lastIndex) { + if (startOffset == 0) startOffset = this->width(); + else startOffset = this->width() - qAbs(startOffset); + } + else { + if (startOffset == 0) startOffset = -this->width(); + else startOffset = qAbs(startOffset) - this->width(); + } + m_moveAnimation->setDuration(qAbs(startOffset) * m_duration / this->width()); + m_moveAnimation->setStartValue(startOffset); + m_moveAnimation->setEndValue(0); + m_moveAnimation->start(); +} + +void AStackWidget::setWidgetsVisible() +{ + int size = count(); + for (int i = 0; i < size; i++) { + if (m_lastIndex == i || m_curIndex == i) + m_widgetLst.at(i)->setVisible(true); + else { + m_widgetLst.at(i)->setVisible(false); + } + } +} + +void AStackWidget::onMoveFinished() +{ + +} diff --git a/netfriend/astackwidget/astackwidget.h b/netfriend/astackwidget/astackwidget.h new file mode 100644 index 0000000..a6c8520 --- /dev/null +++ b/netfriend/astackwidget/astackwidget.h @@ -0,0 +1,52 @@ +#include + +class QPropertyAnimation; +class AStackWidget : public QWidget +{ + Q_OBJECT + +public: + AStackWidget(QWidget *parent); + ~AStackWidget(); + +signals: + void currentChanged(int index); + void widgetRemoved(int index); + +public: + int count() const; + int currentIndex() const; + int addWidget(QWidget *widget); + int indexOf(QWidget *widget) const; + int insertWidget(int index, QWidget *widget); + + QWidget *currentWidget() const; + QWidget *widget(int index) const; + + void removeWidget(QWidget *widget); + void setDuration(int duration); + +public slots: + void setCurrentIndex(int index); + void setCurrentWidget(QWidget *widget); + +private slots: + void onValueChanged(const QVariant &); + void onMoveFinished(); + +private: + void moveAnimationStart(); + void setWidgetsVisible(); + +protected: + void resizeEvent(QResizeEvent *event); + +private: + int m_offset; + int m_curIndex; + int m_lastIndex; + + int m_duration; + QPropertyAnimation *m_moveAnimation; + QList m_widgetLst; +}; diff --git a/netfriend/astackwidget/astackwidget.pro b/netfriend/astackwidget/astackwidget.pro new file mode 100644 index 0000000..ff48b41 --- /dev/null +++ b/netfriend/astackwidget/astackwidget.pro @@ -0,0 +1,16 @@ +QT += core gui +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets +greaterThan(QT_MAJOR_VERSION, 5): QT += core5compat + +TARGET = astackwidget +TEMPLATE = app +DESTDIR = $$PWD/../bin +CONFIG += warn_off + +SOURCES += main.cpp +SOURCES += astackwidget.cpp +HEADERS += astackwidget.h + +SOURCES += frmastackwidget.cpp +HEADERS += frmastackwidget.h +FORMS += frmastackwidget.ui diff --git a/netfriend/astackwidget/frmastackwidget.cpp b/netfriend/astackwidget/frmastackwidget.cpp new file mode 100644 index 0000000..43f5b9d --- /dev/null +++ b/netfriend/astackwidget/frmastackwidget.cpp @@ -0,0 +1,42 @@ +#pragma execution_character_set("utf-8") + +#include "FrmAStackWidget.h" + +#include +#include + +FrmAStackWidget::FrmAStackWidget(QWidget *parent) + : QWidget(parent) +{ + ui.setupUi(this); + + QList colorlst; + colorlst << "#1abc9c"; + colorlst << "#2ecc71"; + colorlst << "#3498db"; + colorlst << "#9b59b6"; + colorlst << "#e74c3c"; + + QList btnlst; + btnlst << ui.pushButton_1; + btnlst << ui.pushButton_2; + btnlst << ui.pushButton_3; + btnlst << ui.pushButton_4; + btnlst << ui.pushButton_5; + + QButtonGroup *btnGroup = new QButtonGroup(this); +#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) + connect(btnGroup, SIGNAL(idClicked(int)), ui.aStackwidget, SLOT(setCurrentIndex(int))); +#else + connect(btnGroup, SIGNAL(buttonClicked(int)), ui.aStackwidget, SLOT(setCurrentIndex(int))); +#endif + + for (int i = 0; i < 5; i++) { + QLabel *label = new QLabel(ui.aStackwidget); + label->setStyleSheet(QString("background-color:%1;color:#ffffff;").arg(colorlst.at(i))); + label->setText(QString::number(i + 1)); + label->setAlignment(Qt::AlignCenter); + int index = ui.aStackwidget->addWidget(label); + btnGroup->addButton(btnlst.at(i), index); + } +} diff --git a/netfriend/astackwidget/frmastackwidget.h b/netfriend/astackwidget/frmastackwidget.h new file mode 100644 index 0000000..794f91c --- /dev/null +++ b/netfriend/astackwidget/frmastackwidget.h @@ -0,0 +1,13 @@ +#include +#include "ui_FrmAStackWidget.h" + +class FrmAStackWidget : public QWidget +{ + Q_OBJECT + +public: + FrmAStackWidget(QWidget *parent = Q_NULLPTR); + +private: + Ui::FrmAStackWidgetClass ui; +}; diff --git a/netfriend/astackwidget/frmastackwidget.ui b/netfriend/astackwidget/frmastackwidget.ui new file mode 100644 index 0000000..d6db1d5 --- /dev/null +++ b/netfriend/astackwidget/frmastackwidget.ui @@ -0,0 +1,94 @@ + + + FrmAStackWidgetClass + + + + 0 + 0 + 600 + 400 + + + + FrmAStackWidget + + + + 12 + + + 12 + + + 12 + + + 12 + + + 12 + + + + + + + PushButton1 + + + + + + + PushButton2 + + + + + + + PushButton3 + + + + + + + PushButton4 + + + + + + + PushButton5 + + + + + + + + + + 0 + 0 + + + + + + + + + + AStackWidget + QWidget +
astackwidget.h
+ 1 +
+
+ + +
diff --git a/netfriend/astackwidget/main.cpp b/netfriend/astackwidget/main.cpp new file mode 100644 index 0000000..ff74030 --- /dev/null +++ b/netfriend/astackwidget/main.cpp @@ -0,0 +1,30 @@ +#pragma execution_character_set("utf-8") +#include "frmastackwidget.h" + +#include +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + a.setFont(QFont("Microsoft Yahei", 9)); + +#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0)) +#if _MSC_VER + QTextCodec *codec = QTextCodec::codecForName("gbk"); +#else + QTextCodec *codec = QTextCodec::codecForName("utf-8"); +#endif + QTextCodec::setCodecForLocale(codec); + QTextCodec::setCodecForCStrings(codec); + QTextCodec::setCodecForTr(codec); +#else + QTextCodec *codec = QTextCodec::codecForName("utf-8"); + QTextCodec::setCodecForLocale(codec); +#endif + + FrmAStackWidget w; + w.setWindowTitle(QStringLiteral("动态StackWidget")); + w.show(); + return a.exec(); +} diff --git a/netfriend/imagecropper/assets/README/001.png b/netfriend/imagecropper/assets/README/001.png new file mode 100644 index 0000000..a6ea589 Binary files /dev/null and b/netfriend/imagecropper/assets/README/001.png differ diff --git a/netfriend/imagecropper/assets/README/002.png b/netfriend/imagecropper/assets/README/002.png new file mode 100644 index 0000000..368f4a4 Binary files /dev/null and b/netfriend/imagecropper/assets/README/002.png differ diff --git a/netfriend/imagecropper/assets/README/003.png b/netfriend/imagecropper/assets/README/003.png new file mode 100644 index 0000000..e0e28e2 Binary files /dev/null and b/netfriend/imagecropper/assets/README/003.png differ diff --git a/netfriend/imagecropper/assets/README/004.png b/netfriend/imagecropper/assets/README/004.png new file mode 100644 index 0000000..ef02015 Binary files /dev/null and b/netfriend/imagecropper/assets/README/004.png differ diff --git a/netfriend/imagecropper/assets/README/005.png b/netfriend/imagecropper/assets/README/005.png new file mode 100644 index 0000000..599ad9c Binary files /dev/null and b/netfriend/imagecropper/assets/README/005.png differ diff --git a/netfriend/imagecropper/assets/README/006.png b/netfriend/imagecropper/assets/README/006.png new file mode 100644 index 0000000..a9b166e Binary files /dev/null and b/netfriend/imagecropper/assets/README/006.png differ diff --git a/netfriend/imagecropper/assets/README/cropper_shape.png b/netfriend/imagecropper/assets/README/cropper_shape.png new file mode 100644 index 0000000..da424ed Binary files /dev/null and b/netfriend/imagecropper/assets/README/cropper_shape.png differ diff --git a/netfriend/imagecropper/assets/README/import_functions.png b/netfriend/imagecropper/assets/README/import_functions.png new file mode 100644 index 0000000..f284bf2 Binary files /dev/null and b/netfriend/imagecropper/assets/README/import_functions.png differ diff --git a/netfriend/imagecropper/base/imagecropperdialog.h b/netfriend/imagecropper/base/imagecropperdialog.h new file mode 100644 index 0000000..2f1696d --- /dev/null +++ b/netfriend/imagecropper/base/imagecropperdialog.h @@ -0,0 +1,99 @@ +#ifndef IMAGECROPPER_H +#define IMAGECROPPER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "imagecropperlabel.h" + +/******************************************************* + * Loacl private class, which do image-cropping + * Used in class ImageCropper +*******************************************************/ +class ImageCropperDialogPrivate : public QDialog +{ + Q_OBJECT +public: + ImageCropperDialogPrivate(const QPixmap &imageIn, QPixmap &outputImage, + int windowWidth, int windowHeight, + CropperShape shape, QSize cropperSize = QSize()) + : QDialog(0) + , outputImage(outputImage) + { + this->setAttribute(Qt::WA_DeleteOnClose, true); + this->setWindowTitle("Image Cropper"); + this->setMouseTracking(true); + this->setModal(true); + + imageLabel = new ImageCropperLabel(windowWidth, windowHeight, this); + imageLabel->setCropper(shape, cropperSize); + imageLabel->setOutputShape(OutputShape::RECT); + imageLabel->setOriginalImage(imageIn); + imageLabel->enableOpacity(true); + + QHBoxLayout *btnLayout = new QHBoxLayout(); + btnOk = new QPushButton("OK", this); + btnCancel = new QPushButton("Cancel", this); + btnLayout->addStretch(); + btnLayout->addWidget(btnOk); + btnLayout->addWidget(btnCancel); + + QVBoxLayout *mainLayout = new QVBoxLayout(this); + mainLayout->addWidget(imageLabel); + mainLayout->addLayout(btnLayout); + + connect(btnOk, &QPushButton::clicked, this, [this]() { + this->outputImage = this->imageLabel->getCroppedImage(); + this->close(); + }); + connect(btnCancel, &QPushButton::clicked, this, [this]() { + this->outputImage = QPixmap(); + this->close(); + }); + } + +private: + ImageCropperLabel *imageLabel; + QPushButton *btnOk; + QPushButton *btnCancel; + QPixmap &outputImage; +}; + +/******************************************************************* + * class ImageCropperDialog + * create a instane of class ImageCropperDialogPrivate + * and get cropped image from the instance(after closing) +********************************************************************/ +class ImageCropperDialog : QObject +{ +public: + static QPixmap getCroppedImage(const QString &filename, int windowWidth, int windowHeight, + CropperShape cropperShape, QSize crooperSize = QSize()) + { + QPixmap inputImage; + QPixmap outputImage; + + if (!inputImage.load(filename)) { + QMessageBox::critical(0, "Error", "Load image failed!", QMessageBox::Ok); + return outputImage; + } + + ImageCropperDialogPrivate *imageCropperDo = + new ImageCropperDialogPrivate(inputImage, outputImage, + windowWidth, windowHeight, + cropperShape, crooperSize); + imageCropperDo->exec(); + + return outputImage; + } +}; + +#endif // IMAGECROPPER_H diff --git a/netfriend/imagecropper/base/imagecropperlabel.cpp b/netfriend/imagecropper/base/imagecropperlabel.cpp new file mode 100644 index 0000000..2800e04 --- /dev/null +++ b/netfriend/imagecropper/base/imagecropperlabel.cpp @@ -0,0 +1,714 @@ +#include "imagecropperlabel.h" + +#include +#include +#include +#include +#include + +ImageCropperLabel::ImageCropperLabel(int width, int height, QWidget* parent) : + QLabel(parent) +{ + this->setFixedSize(width, height); + this->setAlignment(Qt::AlignCenter); + this->setMouseTracking(true); + + borderPen.setWidth(1); + borderPen.setColor(Qt::white); + borderPen.setDashPattern(QVector() << 3 << 3 << 3 << 3); +} + +void ImageCropperLabel::setOriginalImage(const QPixmap &pixmap) { + originalImage = pixmap; + + int imgWidth = pixmap.width(); + int imgHeight = pixmap.height(); + int labelWidth = this->width(); + int labelHeight = this->height(); + int imgWidthInLabel; + int imgHeightInLabel; + + if (imgWidth * labelHeight < imgHeight * labelWidth) { + scaledRate = labelHeight / double(imgHeight); + imgHeightInLabel = labelHeight; + imgWidthInLabel = int(scaledRate * imgWidth); + imageRect.setRect((labelWidth - imgWidthInLabel) / 2, 0, + imgWidthInLabel, imgHeightInLabel); + } + else { + scaledRate = labelWidth / double(imgWidth); + imgWidthInLabel = labelWidth; + imgHeightInLabel = int(scaledRate * imgHeight); + imageRect.setRect(0, (labelHeight - imgHeightInLabel) / 2, + imgWidthInLabel, imgHeightInLabel); + } + + tempImage = originalImage.scaled(imgWidthInLabel, imgHeightInLabel, + Qt::KeepAspectRatio, Qt::SmoothTransformation); + this->setPixmap(tempImage); + + if (cropperShape >= CropperShape::FIXED_RECT) { + cropperRect.setWidth(int(cropperRect_.width() * scaledRate)); + cropperRect.setHeight(int(cropperRect_.height() * scaledRate)); + } + resetCropperPos(); +} + + +/***************************************** + * set cropper's shape (and size) +*****************************************/ +void ImageCropperLabel::setRectCropper() { + cropperShape = CropperShape::RECT; + resetCropperPos(); +} + +void ImageCropperLabel::setSquareCropper() { + cropperShape = CropperShape::SQUARE; + resetCropperPos(); +} + +void ImageCropperLabel::setEllipseCropper() { + cropperShape = CropperShape::ELLIPSE; + resetCropperPos(); +} + +void ImageCropperLabel::setCircleCropper() { + cropperShape = CropperShape::CIRCLE; + resetCropperPos(); +} + +void ImageCropperLabel::setFixedRectCropper(QSize size) { + cropperShape = CropperShape::FIXED_RECT; + cropperRect_.setSize(size); + resetCropperPos(); +} + +void ImageCropperLabel::setFixedEllipseCropper(QSize size) { + cropperShape = CropperShape::FIXED_ELLIPSE; + cropperRect_.setSize(size); + resetCropperPos(); +} + +// not recommended +void ImageCropperLabel::setCropper(CropperShape shape, QSize size) { + cropperShape = shape; + cropperRect_.setSize(size); + resetCropperPos(); +} + +/***************************************************************************** + * Set cropper's fixed size + *****************************************************************************/ +void ImageCropperLabel::setCropperFixedSize(int fixedWidth, int fixedHeight) { + cropperRect_.setSize(QSize(fixedWidth, fixedHeight)); + resetCropperPos(); +} + +void ImageCropperLabel::setCropperFixedWidth(int fixedWidth) { + cropperRect_.setWidth(fixedWidth); + resetCropperPos(); +} + +void ImageCropperLabel::setCropperFixedHeight(int fixedHeight) { + cropperRect_.setHeight(fixedHeight); + resetCropperPos(); +} + +/********************************************** + * Move cropper to the center of the image + * And resize to default +**********************************************/ +void ImageCropperLabel::resetCropperPos() { + int labelWidth = this->width(); + int labelHeight = this->height(); + + if (cropperShape == CropperShape::FIXED_RECT || cropperShape == CropperShape::FIXED_ELLIPSE) { + cropperRect.setWidth(int(cropperRect_.width() * scaledRate)); + cropperRect.setHeight(int(cropperRect_.height() * scaledRate)); + } + + switch (cropperShape) { + case CropperShape::UNDEFINED: + break; + case CropperShape::FIXED_RECT: + case CropperShape::FIXED_ELLIPSE: { + cropperRect.setRect((labelWidth - cropperRect.width()) / 2, + (labelHeight - cropperRect.height()) / 2, + cropperRect.width(), cropperRect.height()); + break; + } + case CropperShape::RECT: + case CropperShape::SQUARE: + case CropperShape::ELLIPSE: + case CropperShape::CIRCLE: { + int imgWidth = tempImage.width(); + int imgHeight = tempImage.height(); + int edge = int((imgWidth > imgHeight ? imgHeight : imgWidth) * 3 / 4.0); + cropperRect.setRect((labelWidth - edge) / 2, (labelHeight - edge) / 2, edge, edge); + break; + } + } +} + +QPixmap ImageCropperLabel::getCroppedImage() { + return getCroppedImage(this->outputShape); +} + +QPixmap ImageCropperLabel::getCroppedImage(OutputShape shape) { + int startX = int((cropperRect.left() - imageRect.left()) / scaledRate); + int startY = int((cropperRect.top() - imageRect.top()) / scaledRate); + int croppedWidth = int(cropperRect.width() / scaledRate); + int croppedHeight = int(cropperRect.height() / scaledRate); + + QPixmap resultImage(croppedWidth, croppedHeight); + resultImage = originalImage.copy(startX, startY, croppedWidth, croppedHeight); + + // Set ellipse mask (cut to ellipse shape) + if (shape == OutputShape::ELLIPSE) { + QSize size(croppedWidth, croppedHeight); + QBitmap mask(size); + QPainter painter(&mask); + painter.setRenderHint(QPainter::Antialiasing); + painter.setRenderHint(QPainter::SmoothPixmapTransform); + painter.fillRect(0, 0, size.width(), size.height(), Qt::white); + painter.setBrush(QColor(0, 0, 0)); + painter.drawRoundedRect(0, 0, size.width(), size.height(), 99, 99); + resultImage.setMask(mask); + } + + return resultImage; +} + + +void ImageCropperLabel::paintEvent(QPaintEvent *event) { + // Draw original image + QLabel::paintEvent(event); + + // Draw cropper and set some effects + switch (cropperShape) { + case CropperShape::UNDEFINED: + break; + case CropperShape::FIXED_RECT: + drawRectOpacity(); + break; + case CropperShape::FIXED_ELLIPSE: + drawEllipseOpacity(); + break; + case CropperShape::RECT: + drawRectOpacity(); + drawSquareEdge(!ONLY_FOUR_CORNERS); + break; + case CropperShape::SQUARE: + drawRectOpacity(); + drawSquareEdge(ONLY_FOUR_CORNERS); + break; + case CropperShape::ELLIPSE: + drawEllipseOpacity(); + drawSquareEdge(!ONLY_FOUR_CORNERS); + break; + case CropperShape::CIRCLE: + drawEllipseOpacity(); + drawSquareEdge(ONLY_FOUR_CORNERS); + break; + } + + // Draw cropper rect + if (isShowRectBorder) { + QPainter painter(this); + painter.setPen(borderPen); + painter.drawRect(cropperRect); + } +} + +void ImageCropperLabel::drawSquareEdge(bool onlyFourCorners) { + if (!isShowDragSquare) + return; + + // Four corners + drawFillRect(cropperRect.topLeft(), dragSquareEdge, dragSquareColor); + drawFillRect(cropperRect.topRight(), dragSquareEdge, dragSquareColor); + drawFillRect(cropperRect.bottomLeft(), dragSquareEdge, dragSquareColor); + drawFillRect(cropperRect.bottomRight(), dragSquareEdge, dragSquareColor); + + // Four edges + if (!onlyFourCorners) { + int centralX = cropperRect.left() + cropperRect.width() / 2; + int centralY = cropperRect.top() + cropperRect.height() / 2; + drawFillRect(QPoint(cropperRect.left(), centralY), dragSquareEdge, dragSquareColor); + drawFillRect(QPoint(centralX, cropperRect.top()), dragSquareEdge, dragSquareColor); + drawFillRect(QPoint(cropperRect.right(), centralY), dragSquareEdge, dragSquareColor); + drawFillRect(QPoint(centralX, cropperRect.bottom()), dragSquareEdge, dragSquareColor); + } +} + +void ImageCropperLabel::drawFillRect(QPoint centralPoint, int edge, QColor color) { + QRect rect(centralPoint.x() - edge / 2, centralPoint.y() - edge / 2, edge, edge); + QPainter painter(this); + painter.fillRect(rect, color); +} + +// Opacity effect +void ImageCropperLabel::drawOpacity(const QPainterPath& path) { + QPainter painterOpac(this); + painterOpac.setOpacity(opacity); + painterOpac.fillPath(path, QBrush(Qt::black)); +} + +void ImageCropperLabel::drawRectOpacity() { + if (isShowOpacityEffect) { + QPainterPath p1, p2, p; + p1.addRect(imageRect); + p2.addRect(cropperRect); + p = p1.subtracted(p2); + drawOpacity(p); + } +} + +void ImageCropperLabel::drawEllipseOpacity() { + if (isShowOpacityEffect) { + QPainterPath p1, p2, p; + p1.addRect(imageRect); + p2.addEllipse(cropperRect); + p = p1.subtracted(p2); + drawOpacity(p); + } +} + +bool ImageCropperLabel::isPosNearDragSquare(const QPoint& pt1, const QPoint& pt2) { + return abs(pt1.x() - pt2.x()) * 2 <= dragSquareEdge + && abs(pt1.y() - pt2.y()) * 2 <= dragSquareEdge; +} + +int ImageCropperLabel::getPosInCropperRect(const QPoint &pt) { + if (isPosNearDragSquare(pt, QPoint(cropperRect.right(), cropperRect.center().y()))) + return RECT_RIGHT; + if (isPosNearDragSquare(pt, cropperRect.bottomRight())) + return RECT_BOTTOM_RIGHT; + if (isPosNearDragSquare(pt, QPoint(cropperRect.center().x(), cropperRect.bottom()))) + return RECT_BOTTOM; + if (isPosNearDragSquare(pt, cropperRect.bottomLeft())) + return RECT_BOTTOM_LEFT; + if (isPosNearDragSquare(pt, QPoint(cropperRect.left(), cropperRect.center().y()))) + return RECT_LEFT; + if (isPosNearDragSquare(pt, cropperRect.topLeft())) + return RECT_TOP_LEFT; + if (isPosNearDragSquare(pt, QPoint(cropperRect.center().x(), cropperRect.top()))) + return RECT_TOP; + if (isPosNearDragSquare(pt, cropperRect.topRight())) + return RECT_TOP_RIGHT; + if (cropperRect.contains(pt, true)) + return RECT_INSIDE; + return RECT_OUTSIZD; +} + +/************************************************* + * + * Change mouse cursor type + * Arrow, SizeHor, SizeVer, etc... + * +*************************************************/ + +void ImageCropperLabel::changeCursor() { + switch (cursorPosInCropperRect) { + case RECT_OUTSIZD: + setCursor(Qt::ArrowCursor); + break; + case RECT_BOTTOM_RIGHT: { + switch (cropperShape) { + case CropperShape::SQUARE: + case CropperShape::CIRCLE: + case CropperShape::RECT: + case CropperShape::ELLIPSE: + setCursor(Qt::SizeFDiagCursor); + break; + default: + break; + } + break; + } + case RECT_RIGHT: { + switch (cropperShape) { + case CropperShape::RECT: + case CropperShape::ELLIPSE: + setCursor(Qt::SizeHorCursor); + break; + default: + break; + } + break; + } + case RECT_BOTTOM: { + switch (cropperShape) { + case CropperShape::RECT: + case CropperShape::ELLIPSE: + setCursor(Qt::SizeVerCursor); + break; + default: + break; + } + break; + } + case RECT_BOTTOM_LEFT: { + switch (cropperShape) { + case CropperShape::RECT: + case CropperShape::ELLIPSE: + case CropperShape::SQUARE: + case CropperShape::CIRCLE: + setCursor(Qt::SizeBDiagCursor); + break; + default: + break; + } + break; + } + case RECT_LEFT: { + switch (cropperShape) { + case CropperShape::RECT: + case CropperShape::ELLIPSE: + setCursor(Qt::SizeHorCursor); + break; + default: + break; + } + break; + } + case RECT_TOP_LEFT: { + switch (cropperShape) { + case CropperShape::RECT: + case CropperShape::ELLIPSE: + case CropperShape::SQUARE: + case CropperShape::CIRCLE: + setCursor(Qt::SizeFDiagCursor); + break; + default: + break; + } + break; + } + case RECT_TOP: { + switch (cropperShape) { + case CropperShape::RECT: + case CropperShape::ELLIPSE: + setCursor(Qt::SizeVerCursor); + break; + default: + break; + } + break; + } + case RECT_TOP_RIGHT: { + switch (cropperShape) { + case CropperShape::SQUARE: + case CropperShape::CIRCLE: + case CropperShape::RECT: + case CropperShape::ELLIPSE: + setCursor(Qt::SizeBDiagCursor); + break; + default: + break; + } + break; + } + case RECT_INSIDE: { + setCursor(Qt::SizeAllCursor); + break; + } + } +} + +/***************************************************** + * + * Mouse Events + * +*****************************************************/ + +void ImageCropperLabel::mousePressEvent(QMouseEvent *e) { + currPos = lastPos = e->pos(); + isLButtonPressed = true; +} + +void ImageCropperLabel::mouseMoveEvent(QMouseEvent *e) { + currPos = e->pos(); + if (!isCursorPosCalculated) { + cursorPosInCropperRect = getPosInCropperRect(currPos); + changeCursor(); + } + + if (!isLButtonPressed) + return; + if (!imageRect.contains(currPos)) + return; + + isCursorPosCalculated = true; + + int xOffset = currPos.x() - lastPos.x(); + int yOffset = currPos.y() - lastPos.y(); + lastPos = currPos; + + int disX = 0; + int disY = 0; + + // Move cropper + switch (cursorPosInCropperRect) { + case RECT_OUTSIZD: + break; + case RECT_BOTTOM_RIGHT: { + disX = currPos.x() - cropperRect.left(); + disY = currPos.y() - cropperRect.top(); + switch (cropperShape) { + case CropperShape::UNDEFINED: + case CropperShape::FIXED_RECT: + case CropperShape::FIXED_ELLIPSE: + break; + case CropperShape::SQUARE: + case CropperShape::CIRCLE: + setCursor(Qt::SizeFDiagCursor); + if (disX >= cropperMinimumWidth && disY >= cropperMinimumHeight) { + if (disX > disY && cropperRect.top() + disX <= imageRect.bottom()) { + cropperRect.setRight(currPos.x()); + cropperRect.setBottom(cropperRect.top() + disX); + emit croppedImageChanged(); + } + else if (disX <= disY && cropperRect.left() + disY <= imageRect.right()) { + cropperRect.setBottom(currPos.y()); + cropperRect.setRight(cropperRect.left() + disY); + emit croppedImageChanged(); + } + } + break; + case CropperShape::RECT: + case CropperShape::ELLIPSE: + setCursor(Qt::SizeFDiagCursor); + if (disX >= cropperMinimumWidth) { + cropperRect.setRight(currPos.x()); + emit croppedImageChanged(); + } + if (disY >= cropperMinimumHeight) { + cropperRect.setBottom(currPos.y()); + emit croppedImageChanged(); + } + break; + } + break; + } + case RECT_RIGHT: { + disX = currPos.x() - cropperRect.left(); + switch (cropperShape) { + case CropperShape::UNDEFINED: + case CropperShape::FIXED_RECT: + case CropperShape::FIXED_ELLIPSE: + case CropperShape::SQUARE: + case CropperShape::CIRCLE: + break; + case CropperShape::RECT: + case CropperShape::ELLIPSE: + if (disX >= cropperMinimumWidth) { + cropperRect.setRight(currPos.x()); + emit croppedImageChanged(); + } + break; + } + break; + } + case RECT_BOTTOM: { + disY = currPos.y() - cropperRect.top(); + switch (cropperShape) { + case CropperShape::UNDEFINED: + case CropperShape::FIXED_RECT: + case CropperShape::FIXED_ELLIPSE: + case CropperShape::SQUARE: + case CropperShape::CIRCLE: + break; + case CropperShape::RECT: + case CropperShape::ELLIPSE: + if (disY >= cropperMinimumHeight) { + cropperRect.setBottom(cropperRect.bottom() + yOffset); + emit croppedImageChanged(); + } + break; + } + break; + } + case RECT_BOTTOM_LEFT: { + disX = cropperRect.right() - currPos.x(); + disY = currPos.y() - cropperRect.top(); + switch (cropperShape) { + case CropperShape::UNDEFINED: + break; + case CropperShape::FIXED_RECT: + case CropperShape::FIXED_ELLIPSE: + case CropperShape::RECT: + case CropperShape::ELLIPSE: + if (disX >= cropperMinimumWidth) { + cropperRect.setLeft(currPos.x()); + emit croppedImageChanged(); + } + if (disY >= cropperMinimumHeight) { + cropperRect.setBottom(currPos.y()); + emit croppedImageChanged(); + } + break; + case CropperShape::SQUARE: + case CropperShape::CIRCLE: + if (disX >= cropperMinimumWidth && disY >= cropperMinimumHeight) { + if (disX > disY && cropperRect.top() + disX <= imageRect.bottom()) { + cropperRect.setLeft(currPos.x()); + cropperRect.setBottom(cropperRect.top() + disX); + emit croppedImageChanged(); + } + else if (disX <= disY && cropperRect.right() - disY >= imageRect.left()) { + cropperRect.setBottom(currPos.y()); + cropperRect.setLeft(cropperRect.right() - disY); + emit croppedImageChanged(); + } + } + break; + } + break; + } + case RECT_LEFT: { + disX = cropperRect.right() - currPos.x(); + switch (cropperShape) { + case CropperShape::UNDEFINED: + case CropperShape::FIXED_RECT: + case CropperShape::FIXED_ELLIPSE: + case CropperShape::SQUARE: + case CropperShape::CIRCLE: + break; + case CropperShape::RECT: + case CropperShape::ELLIPSE: + if (disX >= cropperMinimumHeight) { + cropperRect.setLeft(cropperRect.left() + xOffset); + emit croppedImageChanged(); + } + break; + } + break; + } + case RECT_TOP_LEFT: { + disX = cropperRect.right() - currPos.x(); + disY = cropperRect.bottom() - currPos.y(); + switch (cropperShape) { + case CropperShape::UNDEFINED: + case CropperShape::FIXED_RECT: + case CropperShape::FIXED_ELLIPSE: + break; + case CropperShape::RECT: + case CropperShape::ELLIPSE: + if (disX >= cropperMinimumWidth) { + cropperRect.setLeft(currPos.x()); + emit croppedImageChanged(); + } + if (disY >= cropperMinimumHeight) { + cropperRect.setTop(currPos.y()); + emit croppedImageChanged(); + } + break; + case CropperShape::SQUARE: + case CropperShape::CIRCLE: + if (disX >= cropperMinimumWidth && disY >= cropperMinimumHeight) { + if (disX > disY && cropperRect.bottom() - disX >= imageRect.top()) { + cropperRect.setLeft(currPos.x()); + cropperRect.setTop(cropperRect.bottom() - disX); + emit croppedImageChanged(); + } + else if (disX <= disY && cropperRect.right() - disY >= imageRect.left()) { + cropperRect.setTop(currPos.y()); + cropperRect.setLeft(cropperRect.right() - disY); + emit croppedImageChanged(); + } + } + break; + } + break; + } + case RECT_TOP: { + disY = cropperRect.bottom() - currPos.y(); + switch (cropperShape) { + case CropperShape::UNDEFINED: + case CropperShape::FIXED_RECT: + case CropperShape::FIXED_ELLIPSE: + case CropperShape::SQUARE: + case CropperShape::CIRCLE: + break; + case CropperShape::RECT: + case CropperShape::ELLIPSE: + if (disY >= cropperMinimumHeight) { + cropperRect.setTop(cropperRect.top() + yOffset); + emit croppedImageChanged(); + } + break; + } + break; + } + case RECT_TOP_RIGHT: { + disX = currPos.x() - cropperRect.left(); + disY = cropperRect.bottom() - currPos.y(); + switch (cropperShape) { + case CropperShape::UNDEFINED: + case CropperShape::FIXED_RECT: + case CropperShape::FIXED_ELLIPSE: + break; + case CropperShape::RECT: + case CropperShape::ELLIPSE: + if (disX >= cropperMinimumWidth) { + cropperRect.setRight(currPos.x()); + emit croppedImageChanged(); + } + if (disY >= cropperMinimumHeight) { + cropperRect.setTop(currPos.y()); + emit croppedImageChanged(); + } + break; + case CropperShape::SQUARE: + case CropperShape::CIRCLE: + if (disX >= cropperMinimumWidth && disY >= cropperMinimumHeight) { + if (disX < disY && cropperRect.left() + disY <= imageRect.right()) { + cropperRect.setTop(currPos.y()); + cropperRect.setRight(cropperRect.left() + disY); + emit croppedImageChanged(); + } + else if (disX >= disY && cropperRect.bottom() - disX >= imageRect.top()) { + cropperRect.setRight(currPos.x()); + cropperRect.setTop(cropperRect.bottom() - disX); + emit croppedImageChanged(); + } + } + break; + } + break; + } + case RECT_INSIDE: { + // Make sure the cropperRect is entirely inside the imageRecct + if (xOffset > 0) { + if (cropperRect.right() + xOffset > imageRect.right()) + xOffset = 0; + } + else if (xOffset < 0) { + if (cropperRect.left() + xOffset < imageRect.left()) + xOffset = 0; + } + if (yOffset > 0) { + if (cropperRect.bottom() + yOffset > imageRect.bottom()) + yOffset = 0; + } + else if (yOffset < 0) { + if (cropperRect.top() + yOffset < imageRect.top()) + yOffset = 0; + } + cropperRect.moveTo(cropperRect.left() + xOffset, cropperRect.top() + yOffset); + emit croppedImageChanged(); + } + break; + } + + repaint(); +} + +void ImageCropperLabel::mouseReleaseEvent(QMouseEvent *) { + isLButtonPressed = false; + isCursorPosCalculated = false; + setCursor(Qt::ArrowCursor); +} + diff --git a/netfriend/imagecropper/base/imagecropperlabel.h b/netfriend/imagecropper/base/imagecropperlabel.h new file mode 100644 index 0000000..5c79471 --- /dev/null +++ b/netfriend/imagecropper/base/imagecropperlabel.h @@ -0,0 +1,168 @@ +#ifndef IMAGECROPPERLABEL_H +#define IMAGECROPPERLABEL_H + +#include +#include +#include + +enum class CropperShape { + UNDEFINED = 0, + RECT = 1, + SQUARE = 2, + FIXED_RECT = 3, + ELLIPSE = 4, + CIRCLE = 5, + FIXED_ELLIPSE = 6 +}; + +enum class OutputShape { + RECT = 0, + ELLIPSE = 1 +}; + +enum class SizeType { + fixedSize = 0, + fitToMaxWidth = 1, + fitToMaxHeight = 2, + fitToMaxWidthHeight = 3, +}; + +class ImageCropperLabel : public QLabel +{ + Q_OBJECT +public: + ImageCropperLabel(int width, int height, QWidget *parent); + + void setOriginalImage(const QPixmap &pixmap); + void setOutputShape(OutputShape shape) { outputShape = shape; } + QPixmap getCroppedImage(); + QPixmap getCroppedImage(OutputShape shape); + + /***************************************** + * Set cropper's shape + *****************************************/ + void setRectCropper(); + void setSquareCropper(); + void setEllipseCropper(); + void setCircleCropper(); + void setFixedRectCropper(QSize size); + void setFixedEllipseCropper(QSize size); + void setCropper(CropperShape shape, QSize size); // not recommended + + /***************************************************************************** + * Set cropper's fixed size + *****************************************************************************/ + void setCropperFixedSize(int fixedWidth, int fixedHeight); + void setCropperFixedWidth(int fixedWidht); + void setCropperFixedHeight(int fixedHeight); + + /***************************************************************************** + * Set cropper's minimum size + * default: the twice of minimum of the edge lenght of drag square + *****************************************************************************/ + void setCropperMinimumSize(int minWidth, int minHeight) + { + cropperMinimumWidth = minWidth; + cropperMinimumHeight = minHeight; + } + void setCropperMinimumWidth(int minWidth) { cropperMinimumWidth = minWidth; } + void setCropperMinimumHeight(int minHeight) { cropperMinimumHeight = minHeight; } + + /************************************************* + * Set the size, color, visibility of rectangular border + *************************************************/ + void setShowRectBorder(bool show) { isShowRectBorder = show; } + QPen getBorderPen() { return borderPen; } + void setBorderPen(const QPen &pen) { borderPen = pen; } + + /************************************************* + * Set the size, color of drag square + *************************************************/ + void setShowDragSquare(bool show) { isShowDragSquare = show; } + void setDragSquareEdge(int edge) { dragSquareEdge = (edge >= 3 ? edge : 3); } + void setDragSquareColor(const QColor &color) { dragSquareColor = color; } + + /***************************************** + * Opacity Effect + *****************************************/ + void enableOpacity(bool b = true) { isShowOpacityEffect = b; } + void setOpacity(double newOpacity) { opacity = newOpacity; } + +signals: + void croppedImageChanged(); + +protected: + /***************************************** + * Event + *****************************************/ + virtual void paintEvent(QPaintEvent *event) override; + virtual void mousePressEvent(QMouseEvent *e) override; + virtual void mouseMoveEvent(QMouseEvent *e) override; + virtual void mouseReleaseEvent(QMouseEvent *e) override; + +private: + /*************************************** + * Draw shapes + ***************************************/ + void drawFillRect(QPoint centralPoint, int edge, QColor color); + void drawRectOpacity(); + void drawEllipseOpacity(); + void drawOpacity(const QPainterPath &path); // shadow effect + void drawSquareEdge(bool onlyFourCorners); + + /*************************************** + * Other utility methods + ***************************************/ + int getPosInCropperRect(const QPoint &pt); + bool isPosNearDragSquare(const QPoint &pt1, const QPoint &pt2); + void resetCropperPos(); + void changeCursor(); + + enum { + RECT_OUTSIZD = 0, + RECT_INSIDE = 1, + RECT_TOP_LEFT, + RECT_TOP, + RECT_TOP_RIGHT, + RECT_RIGHT, + RECT_BOTTOM_RIGHT, + RECT_BOTTOM, + RECT_BOTTOM_LEFT, + RECT_LEFT + }; + + const bool ONLY_FOUR_CORNERS = true; + +private: + QPixmap originalImage; + QPixmap tempImage; + + bool isShowRectBorder = true; + QPen borderPen; + + CropperShape cropperShape = CropperShape::UNDEFINED; + OutputShape outputShape = OutputShape::RECT; + + QRect imageRect; // the whole image area in the label (not real size) + QRect cropperRect; // a rectangle frame to choose image area (not real size) + QRect cropperRect_; // cropper rect (real size) + double scaledRate = 1.0; + + bool isLButtonPressed = false; + bool isCursorPosCalculated = false; + int cursorPosInCropperRect = RECT_OUTSIZD; + QPoint lastPos; + QPoint currPos; + + bool isShowDragSquare = true; + int dragSquareEdge = 8; + QColor dragSquareColor = Qt::white; + + int cropperMinimumWidth = dragSquareEdge * 2; + int cropperMinimumHeight = dragSquareEdge * 2; + + bool isShowOpacityEffect = false; + double opacity = 0.6; +}; + +#endif // IMAGECROPPERLABEL_H diff --git a/netfriend/imagecropper/example/imagecropperdemo.cpp b/netfriend/imagecropper/example/imagecropperdemo.cpp new file mode 100644 index 0000000..995d137 --- /dev/null +++ b/netfriend/imagecropper/example/imagecropperdemo.cpp @@ -0,0 +1,415 @@ +#include "imagecropperdemo.h" +#include +#include +#include +#include +#include + +ImageCropperDemo::ImageCropperDemo(QWidget* parent) : + QDialog(parent) +{ + setupLayout(); + init(); + + this->setAttribute(Qt::WA_DeleteOnClose, true); + this->setWindowTitle("Image Cropper Demo"); +} + + +void ImageCropperDemo::setupLayout() { + imgCropperLabel = new ImageCropperLabel(600, 500, this); + imgCropperLabel->setFrameStyle(1); + + comboOutputShape = new QComboBox(this); + comboCropperShape = new QComboBox(this); + + labelPreviewImage = new QLabel(this); + + editOriginalImagePath = new QLineEdit(this); + btnChooseOriginalImagePath = new QPushButton(this); + QHBoxLayout* hOriginalImagePathLayout = new QHBoxLayout(); + hOriginalImagePathLayout->addWidget(editOriginalImagePath); + hOriginalImagePathLayout->addWidget(btnChooseOriginalImagePath); + + editCropperFixedWidth = new QLineEdit(this); + editCropperFixedHeight = new QLineEdit(this); + QHBoxLayout* hCropperFixedSizeLayout = new QHBoxLayout(); + hCropperFixedSizeLayout->addWidget(editCropperFixedWidth); + hCropperFixedSizeLayout->addWidget(editCropperFixedHeight); + + editCropperMinWidth = new QLineEdit("8", this); + editCropperMinHeight = new QLineEdit("8", this); + QHBoxLayout* hCropperMinSizeLayout = new QHBoxLayout(); + hCropperMinSizeLayout->addWidget(editCropperMinWidth); + hCropperMinSizeLayout->addWidget(editCropperMinHeight); + + checkEnableOpacity = new QCheckBox(this); + sliderOpacity = new QSlider(Qt::Horizontal, this); + + checkShowDragSquare = new QCheckBox(this); + editDragSquareEdge = new QLineEdit("8", this); + checkShowRectBorder = new QCheckBox(this); + + labelRectBorderColor = new QLabel(this); + btnChooseRectBorderCorlor = new QPushButton(this); + QHBoxLayout* hRectBorderColorLayout = new QHBoxLayout(); + hRectBorderColorLayout->addWidget(labelRectBorderColor); + hRectBorderColorLayout->addWidget(btnChooseRectBorderCorlor); + + labelDragSquareColor = new QLabel(this); + btnChooseDragSquareColor = new QPushButton(this); + QHBoxLayout* hDragSquareColorLayout = new QHBoxLayout(); + hDragSquareColorLayout->addWidget(labelDragSquareColor); + hDragSquareColorLayout->addWidget(btnChooseDragSquareColor); + + QFormLayout* formLayout1 = new QFormLayout(); + formLayout1->addRow(new QLabel("Preview:"), labelPreviewImage); + formLayout1->addRow(new QLabel("OriginalImage:", this), hOriginalImagePathLayout); + formLayout1->addRow(new QLabel("OutputShape:", this), comboOutputShape); + formLayout1->addRow(new QLabel("CropperShape:", this), comboCropperShape); + formLayout1->addRow(new QLabel("FixedSize:", this), hCropperFixedSizeLayout); + formLayout1->addRow(new QLabel("MinimumSize:", this), hCropperMinSizeLayout); + + QFormLayout* formLayout2 = new QFormLayout(); + formLayout2->addRow(new QLabel("EnableOpacity:", this), checkEnableOpacity); + formLayout2->addRow(new QLabel("Opacity:", this), sliderOpacity); + + QFormLayout* formLayout3 = new QFormLayout(); + formLayout3->addRow(new QLabel("ShowDragSquare:", this), checkShowDragSquare); + formLayout3->addRow(new QLabel("DragSquareEdge:", this), editDragSquareEdge); + formLayout3->addRow(new QLabel("DragSquareColor:", this), hDragSquareColorLayout); + + QFormLayout* formLayout4 = new QFormLayout(); + formLayout4->addRow(new QLabel("ShowRectBorder:", this), checkShowRectBorder); + formLayout4->addRow(new QLabel("RectBorderColor:", this), hRectBorderColorLayout); + + btnSavePreview = new QPushButton("Save", this); + btnQuit = new QPushButton("Quit", this); + QHBoxLayout* btnLayout = new QHBoxLayout(); + btnLayout->addStretch(); + btnLayout->addWidget(btnSavePreview); + btnLayout->addStretch(); + btnLayout->addWidget(btnQuit); + btnLayout->addStretch(); + + QVBoxLayout* vLayout = new QVBoxLayout(); + vLayout->addLayout(formLayout1); + vLayout->addStretch(); + vLayout->addLayout(formLayout2); + vLayout->addStretch(); + vLayout->addLayout(formLayout3); + vLayout->addStretch(); + vLayout->addLayout(formLayout4); + vLayout->addStretch(); + vLayout->addLayout(btnLayout); + + mainLayout = new QHBoxLayout(this); + mainLayout->addWidget(imgCropperLabel); + mainLayout->addLayout(vLayout); +} + +void ImageCropperDemo::init() { + imgCropperLabel->setRectCropper(); + editCropperFixedWidth->setEnabled(false); + editCropperFixedHeight->setEnabled(false); + + labelPreviewImage->setFixedSize(96, 96); + labelPreviewImage->setAlignment(Qt::AlignCenter); + labelPreviewImage->setFrameStyle(QFrame::Panel | QFrame::Sunken); + connect(imgCropperLabel, &ImageCropperLabel::croppedImageChanged, + this, &ImageCropperDemo::onUpdatePreview); + + btnChooseOriginalImagePath->setIcon(QIcon("res/select-file.ico")); + btnChooseOriginalImagePath->setFixedWidth(30); + connect(btnChooseOriginalImagePath, &QPushButton::clicked, + this, &ImageCropperDemo::onChooseOriginalImage); + + comboOutputShape->addItem("Rect/Square"); + comboOutputShape->addItem("Ellipse/Circle"); + connect(comboOutputShape, SIGNAL(currentIndexChanged(int)), + this, SLOT(onOutputShapeChanged(int))); + + comboCropperShape->addItem("Rect"); + comboCropperShape->addItem("Square"); + comboCropperShape->addItem("FixedRect"); + comboCropperShape->addItem("Ellipse"); + comboCropperShape->addItem("Circle"); + comboCropperShape->addItem("FixedEllipse"); + connect(comboCropperShape, SIGNAL(currentIndexChanged(int)), + this, SLOT(onCropperShapeChanged(int))); + + connect(editCropperFixedWidth, &QLineEdit::textChanged, + this, &ImageCropperDemo::onFixedWidthChanged); + connect(editCropperFixedHeight, &QLineEdit::textChanged, + this, &ImageCropperDemo::onFixedHeightChanged); + connect(editCropperMinWidth, &QLineEdit::textChanged, + this, &ImageCropperDemo::onMinWidthChanged); + connect(editCropperMinHeight, &QLineEdit::textChanged, + this, &ImageCropperDemo::onMinHeightChanged); + + checkEnableOpacity->setCheckState(Qt::Checked); + imgCropperLabel->enableOpacity(true); + connect(checkEnableOpacity, &QCheckBox::stateChanged, + this, &ImageCropperDemo::onEnableOpacityChanged); + + checkShowDragSquare->setCheckState(Qt::Checked); + imgCropperLabel->setShowDragSquare(true); + connect(checkShowDragSquare, &QCheckBox::stateChanged, + this, &ImageCropperDemo::onShowDragSquareChanged); + connect(editDragSquareEdge, &QLineEdit::textChanged, + this, &ImageCropperDemo::onDragSquareEdgeChanged); + + sliderOpacity->setRange(0, 100); + sliderOpacity->setValue(60); + connect(sliderOpacity, &QSlider::valueChanged, + this, &ImageCropperDemo::onOpacityChanged); + + checkShowRectBorder->setCheckState(Qt::Checked); + connect(checkShowRectBorder, &QCheckBox::stateChanged, + this, &ImageCropperDemo::onShowRectBorder); + + setLabelColor(labelRectBorderColor, Qt::white); + btnChooseRectBorderCorlor->setIcon(QIcon("res/color-palette.ico")); + btnChooseRectBorderCorlor->setFixedWidth(40); + connect(btnChooseRectBorderCorlor, &QPushButton::clicked, + this, &ImageCropperDemo::onChooseRectBorderColor); + + setLabelColor(labelDragSquareColor, Qt::white); + btnChooseDragSquareColor->setIcon(QIcon("res/color-palette.ico")); + btnChooseDragSquareColor->setFixedWidth(40); + connect(btnChooseDragSquareColor, &QPushButton::clicked, + this, &ImageCropperDemo::onChooseDragSquareColor); + + connect(btnSavePreview, &QPushButton::clicked, + this, &ImageCropperDemo::onSaveCroppedImage); + connect(btnQuit, &QPushButton::clicked, + this, &ImageCropperDemo::close); + + imgCropperLabel->update(); +} + + +/***************************************************************************** + * + * slots + * +*****************************************************************************/ + +void ImageCropperDemo::onChooseOriginalImage() { + QString filename = QFileDialog::getOpenFileName(this, "Select a picture", "", + "picture (*.jpg *.png *.bmp)"); + if (filename.isNull()) + return; + + QPixmap pixmap; + if (!pixmap.load(filename)) { + QMessageBox::critical(this, "Error", "Load image failed", QMessageBox::Ok); + return; + } + + editOriginalImagePath->setText(filename); + imgCropperLabel->setOriginalImage(pixmap); + imgCropperLabel->update(); + onUpdatePreview(); + labelPreviewImage->setFrameStyle(0); +} + +void ImageCropperDemo::onOutputShapeChanged(int idx) { + // Output: Rectangular + if (idx == 0) + imgCropperLabel->setOutputShape(OutputShape::RECT); + else + imgCropperLabel->setOutputShape(OutputShape::ELLIPSE); + onUpdatePreview(); +} + +void ImageCropperDemo::onCropperShapeChanged(int idx) { + switch (CropperShape(idx + 1)) { + case CropperShape::RECT: { + imgCropperLabel->setRectCropper(); + editCropperFixedWidth->setEnabled(false); + editCropperFixedHeight->setEnabled(false); + editCropperMinWidth->setEnabled(true); + editCropperMinHeight->setEnabled(true); + checkShowDragSquare->setEnabled(true); + editDragSquareEdge->setEnabled(true); + btnChooseDragSquareColor->setEnabled(true); + break; + } + case CropperShape::SQUARE: { + imgCropperLabel->setSquareCropper(); + editCropperFixedWidth->setEnabled(false); + editCropperFixedHeight->setEnabled(false); + editCropperMinWidth->setEnabled(true); + editCropperMinHeight->setEnabled(true); + checkShowDragSquare->setEnabled(true); + editDragSquareEdge->setEnabled(true); + btnChooseDragSquareColor->setEnabled(true); + break; + } + case CropperShape::FIXED_RECT: { + imgCropperLabel->setFixedRectCropper(QSize(64, 64)); + editCropperFixedWidth->setEnabled(true); + editCropperFixedHeight->setEnabled(true); + editCropperMinWidth->setEnabled(false); + editCropperMinHeight->setEnabled(false); + editCropperFixedWidth->setText("64"); + editCropperFixedHeight->setText("64"); + checkShowDragSquare->setEnabled(false); + editDragSquareEdge->setEnabled(false); + btnChooseDragSquareColor->setEnabled(false); + break; + } + case CropperShape::ELLIPSE: { + imgCropperLabel->setEllipseCropper(); + editCropperFixedWidth->setEnabled(false); + editCropperFixedHeight->setEnabled(false); + editCropperMinWidth->setEnabled(true); + editCropperMinHeight->setEnabled(true); + checkShowDragSquare->setEnabled(true); + editDragSquareEdge->setEnabled(true); + btnChooseDragSquareColor->setEnabled(true); + break; + } + case CropperShape::CIRCLE: { + imgCropperLabel->setCircleCropper(); + editCropperFixedWidth->setEnabled(false); + editCropperFixedHeight->setEnabled(false); + editCropperMinWidth->setEnabled(true); + editCropperMinHeight->setEnabled(true); + checkShowDragSquare->setEnabled(true); + editDragSquareEdge->setEnabled(true); + btnChooseDragSquareColor->setEnabled(true); + break; + } + case CropperShape::FIXED_ELLIPSE: + imgCropperLabel->setFixedEllipseCropper(QSize(64, 64)); + editCropperFixedWidth->setEnabled(true); + editCropperFixedHeight->setEnabled(true); + editCropperMinWidth->setEnabled(false); + editCropperMinHeight->setEnabled(false); + editCropperFixedWidth->setText("64"); + editCropperFixedHeight->setText("64"); + checkShowDragSquare->setEnabled(false); + editDragSquareEdge->setEnabled(false); + btnChooseDragSquareColor->setEnabled(false); + break; + case CropperShape::UNDEFINED: + break; + } + + imgCropperLabel->update(); + onUpdatePreview(); +} + +void ImageCropperDemo::onEnableOpacityChanged(int state) { + if (state == Qt::Checked) { + sliderOpacity->setEnabled(true); + imgCropperLabel->enableOpacity(true); + } + else { + sliderOpacity->setEnabled(false); + imgCropperLabel->enableOpacity(false); + } + imgCropperLabel->update(); +} + +void ImageCropperDemo::onShowDragSquareChanged(int state) { + if (state == Qt::Checked) { + editDragSquareEdge->setEnabled(true); + btnChooseDragSquareColor->setEnabled(true); + imgCropperLabel->setShowDragSquare(true); + } + else { + editDragSquareEdge->setEnabled(false); + btnChooseDragSquareColor->setEnabled(false); + imgCropperLabel->setShowDragSquare(false); + } + imgCropperLabel->update(); +} + +void ImageCropperDemo::onDragSquareEdgeChanged(QString edge) { + imgCropperLabel->setDragSquareEdge(edge.toInt()); + imgCropperLabel->update(); +} + +void ImageCropperDemo::onOpacityChanged(int val) { + imgCropperLabel->setOpacity(val / 100.0); + imgCropperLabel->update(); +} + +void ImageCropperDemo::onFixedWidthChanged(QString width) { + imgCropperLabel->setCropperFixedWidth(width.toInt()); + imgCropperLabel->update(); +} + +void ImageCropperDemo::onFixedHeightChanged(QString height) { + imgCropperLabel->setCropperFixedHeight(height.toInt()); + imgCropperLabel->update(); +} + +void ImageCropperDemo::onMinWidthChanged(QString width) { + imgCropperLabel->setCropperMinimumWidth(width.toInt()); + imgCropperLabel->update(); +} + +void ImageCropperDemo::onMinHeightChanged(QString height) { + imgCropperLabel->setMinimumHeight(height.toInt()); + imgCropperLabel->update(); +} + +void ImageCropperDemo::onShowRectBorder(int state) { + if (state == Qt::Checked) { + btnChooseRectBorderCorlor->setEnabled(true); + imgCropperLabel->setShowRectBorder(true); + } + else { + btnChooseRectBorderCorlor->setEnabled(false); + imgCropperLabel->setShowRectBorder(false); + } + imgCropperLabel->update(); +} + +void ImageCropperDemo::onChooseRectBorderColor() { + QColor color = QColorDialog::getColor(imgCropperLabel->getBorderPen().color(), this); + if (color.isValid()) { + setLabelColor(labelRectBorderColor, color); + QPen pen = imgCropperLabel->getBorderPen(); + pen.setColor(color); + imgCropperLabel->setBorderPen(pen); + imgCropperLabel->update(); + } +} + +void ImageCropperDemo::onChooseDragSquareColor() { + QColor color = QColorDialog::getColor(Qt::white, this); + if (color.isValid()) { + setLabelColor(labelDragSquareColor, color); + imgCropperLabel->setDragSquareColor(color); + imgCropperLabel->update(); + } +} + +void ImageCropperDemo::onUpdatePreview() { + QPixmap preview = imgCropperLabel->getCroppedImage(); + preview = preview.scaled(labelPreviewImage->width(), labelPreviewImage->height(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); + labelPreviewImage->setPixmap(preview); +} + +void ImageCropperDemo::onSaveCroppedImage() { + const QPixmap* pixmap = labelPreviewImage->pixmap(); + if (!pixmap) { + QMessageBox::information(this, "Error", "There is no cropped image to save.", QMessageBox::Ok); + return ; + } + + QString filename = QFileDialog::getSaveFileName(this, "Save cropped image", "", "picture (*.png)"); + if (!filename.isNull()) { + if (imgCropperLabel->getCroppedImage().save(filename, "PNG")) + QMessageBox::information(this, "Prompt", "Saved successfully", QMessageBox::Ok); + else + QMessageBox::information(this, "Error", "Save image failed!", QMessageBox::Ok); + } +} + diff --git a/netfriend/imagecropper/example/imagecropperdemo.h b/netfriend/imagecropper/example/imagecropperdemo.h new file mode 100644 index 0000000..b9388d8 --- /dev/null +++ b/netfriend/imagecropper/example/imagecropperdemo.h @@ -0,0 +1,85 @@ +#ifndef TESTIMAGECROPPERLABEL_H +#define TESTIMAGECROPPERLABEL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../base/imagecropperlabel.h" + +class ImageCropperDemo : public QDialog +{ + Q_OBJECT +public: + ImageCropperDemo(QWidget* parent = 0); + + void setupLayout(); + + void init(); + +public slots: + void onOutputShapeChanged(int idx); + void onCropperShapeChanged(int idx); + void onEnableOpacityChanged(int state); + void onShowDragSquareChanged(int state); + void onDragSquareEdgeChanged(QString edge); + void onOpacityChanged(int val); + void onFixedWidthChanged(QString width); + void onFixedHeightChanged(QString height); + void onMinWidthChanged(QString width); + void onMinHeightChanged(QString height); + void onShowRectBorder(int state); + void onChooseRectBorderColor(); + void onChooseDragSquareColor(); + + void onChooseOriginalImage(); + void onUpdatePreview(); + void onSaveCroppedImage(); + +private: + void setLabelColor(QLabel* label, QColor color) { + QPixmap pixmap(QSize(80, 25)); + pixmap.fill(color); + label->setPixmap(pixmap); + } + +private: + ImageCropperLabel* imgCropperLabel; + QHBoxLayout* mainLayout; + + QLabel* labelPreviewImage; + + QComboBox* comboOutputShape; + QComboBox* comboCropperShape; + + QLineEdit* editOriginalImagePath; + QPushButton* btnChooseOriginalImagePath; + + QLineEdit* editCropperFixedWidth; + QLineEdit* editCropperFixedHeight; + QLineEdit* editCropperMinWidth; + QLineEdit* editCropperMinHeight; + + QCheckBox* checkShowDragSquare; + QCheckBox* checkEnableOpacity; + QSlider* sliderOpacity; + QLineEdit* editDragSquareEdge; + + QCheckBox* checkShowRectBorder; + QLabel* labelRectBorderColor; + QPushButton* btnChooseRectBorderCorlor; + + QLabel* labelDragSquareColor; + QPushButton* btnChooseDragSquareColor; + + QPushButton* btnSavePreview; + QPushButton* btnQuit; +}; + +#endif // TESTIMAGECROPPERLABEL_H diff --git a/netfriend/imagecropper/example/main.cpp b/netfriend/imagecropper/example/main.cpp new file mode 100644 index 0000000..fd3e533 --- /dev/null +++ b/netfriend/imagecropper/example/main.cpp @@ -0,0 +1,11 @@ +#include "mainwindow.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + return a.exec(); +} diff --git a/netfriend/imagecropper/example/mainwindow.cpp b/netfriend/imagecropper/example/mainwindow.cpp new file mode 100644 index 0000000..b9c6a31 --- /dev/null +++ b/netfriend/imagecropper/example/mainwindow.cpp @@ -0,0 +1,62 @@ +#include "mainwindow.h" +#include "imagecropperdemo.h" + +#include "../base/imagecropperdialog.h" + +#include +#include +#include + + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) +{ + setupLayout(); +} + +MainWindow::~MainWindow() +{ +} + +void MainWindow::setupLayout() { + QWidget* centralWidget = new QWidget(this); + + btnCustomCrop = new QPushButton("Custom Crop", centralWidget); + btnSimpleCrop = new QPushButton("Simple Crop", centralWidget); + + QVBoxLayout* mainLayout = new QVBoxLayout(centralWidget); + mainLayout->addWidget(btnCustomCrop); + mainLayout->addWidget(btnSimpleCrop); + this->setCentralWidget(centralWidget); + + connect(btnCustomCrop, &QPushButton::clicked, this, &MainWindow::onCustomCrop); + connect(btnSimpleCrop, &QPushButton::clicked, this, &MainWindow::onSimpleCrop); +} + +void MainWindow::onCustomCrop() { + ImageCropperDemo* dialog = new ImageCropperDemo(this); + dialog->show(); +} + +void MainWindow::onSimpleCrop() { + QMessageBox::information(this, "Prompt", "Please select a picture", QMessageBox::Ok); + QString filename = QFileDialog::getOpenFileName(this, "Select image", "", "image (*.png *.jpg)"); + if (filename.isNull()) + return; + + // ********* + // ******* + // ***** + // *** + // * + QPixmap image = ImageCropperDialog::getCroppedImage(filename, 600, 400, CropperShape::CIRCLE); + if (image.isNull()) + return; + + QDialog* dialog = new QDialog(0); + dialog->setAttribute(Qt::WA_DeleteOnClose, true); + QLabel* label = new QLabel(dialog); + label->setFixedSize(image.size()); + label->setPixmap(image); + dialog->exec(); +} diff --git a/netfriend/imagecropper/example/mainwindow.h b/netfriend/imagecropper/example/mainwindow.h new file mode 100644 index 0000000..333fc74 --- /dev/null +++ b/netfriend/imagecropper/example/mainwindow.h @@ -0,0 +1,26 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = 0); + ~MainWindow(); + +public slots: + void onCustomCrop(); + void onSimpleCrop(); + +private: + void setupLayout(); + +private: + QPushButton* btnCustomCrop; + QPushButton* btnSimpleCrop; +}; +#endif // MAINWINDOW_H diff --git a/netfriend/imagecropper/imagecropper.pro b/netfriend/imagecropper/imagecropper.pro new file mode 100644 index 0000000..34f8c17 --- /dev/null +++ b/netfriend/imagecropper/imagecropper.pro @@ -0,0 +1,20 @@ +QT += core gui +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets +greaterThan(QT_MAJOR_VERSION, 5): QT += core5compat + +TEMPLATE = app +DESTDIR = $$PWD/../bin +CONFIG += warn_off +CONFIG += c++11 + +SOURCES += \ + base/imagecropperlabel.cpp \ + example/imagecropperdemo.cpp \ + example/main.cpp \ + example/mainwindow.cpp + +HEADERS += \ + base/imagecropperdialog.h \ + base/imagecropperlabel.h \ + example/imagecropperdemo.h \ + example/mainwindow.h diff --git a/netfriend/imagecropper/res/color-palette.ico b/netfriend/imagecropper/res/color-palette.ico new file mode 100644 index 0000000..b046713 Binary files /dev/null and b/netfriend/imagecropper/res/color-palette.ico differ diff --git a/netfriend/imagecropper/res/save.ico b/netfriend/imagecropper/res/save.ico new file mode 100644 index 0000000..39de3e6 Binary files /dev/null and b/netfriend/imagecropper/res/save.ico differ diff --git a/netfriend/imagecropper/res/select-file.ico b/netfriend/imagecropper/res/select-file.ico new file mode 100644 index 0000000..1ef4c60 Binary files /dev/null and b/netfriend/imagecropper/res/select-file.ico differ diff --git a/netfriend/imageviewwindow/Resources/1.jpg b/netfriend/imageviewwindow/Resources/1.jpg new file mode 100644 index 0000000..cb7f271 Binary files /dev/null and b/netfriend/imageviewwindow/Resources/1.jpg differ diff --git a/netfriend/imageviewwindow/Resources/2.jpg b/netfriend/imageviewwindow/Resources/2.jpg new file mode 100644 index 0000000..99726b3 Binary files /dev/null and b/netfriend/imageviewwindow/Resources/2.jpg differ diff --git a/netfriend/imageviewwindow/Resources/3.jpg b/netfriend/imageviewwindow/Resources/3.jpg new file mode 100644 index 0000000..86e5e3a Binary files /dev/null and b/netfriend/imageviewwindow/Resources/3.jpg differ diff --git a/netfriend/imageviewwindow/Resources/4.jpg b/netfriend/imageviewwindow/Resources/4.jpg new file mode 100644 index 0000000..139a17c Binary files /dev/null and b/netfriend/imageviewwindow/Resources/4.jpg differ diff --git a/netfriend/imageviewwindow/Resources/5.jpg b/netfriend/imageviewwindow/Resources/5.jpg new file mode 100644 index 0000000..41c2db3 Binary files /dev/null and b/netfriend/imageviewwindow/Resources/5.jpg differ diff --git a/netfriend/imageviewwindow/Resources/6.jpg b/netfriend/imageviewwindow/Resources/6.jpg new file mode 100644 index 0000000..dbe1c97 Binary files /dev/null and b/netfriend/imageviewwindow/Resources/6.jpg differ diff --git a/netfriend/imageviewwindow/Resources/7.jpg b/netfriend/imageviewwindow/Resources/7.jpg new file mode 100644 index 0000000..f23f324 Binary files /dev/null and b/netfriend/imageviewwindow/Resources/7.jpg differ diff --git a/netfriend/imageviewwindow/Resources/Wblog_left.png b/netfriend/imageviewwindow/Resources/Wblog_left.png new file mode 100644 index 0000000..ff05dea Binary files /dev/null and b/netfriend/imageviewwindow/Resources/Wblog_left.png differ diff --git a/netfriend/imageviewwindow/Resources/Wblog_right.png b/netfriend/imageviewwindow/Resources/Wblog_right.png new file mode 100644 index 0000000..1480069 Binary files /dev/null and b/netfriend/imageviewwindow/Resources/Wblog_right.png differ diff --git a/netfriend/imageviewwindow/graphicspixmap.cpp b/netfriend/imageviewwindow/graphicspixmap.cpp new file mode 100644 index 0000000..d2dfaf2 --- /dev/null +++ b/netfriend/imageviewwindow/graphicspixmap.cpp @@ -0,0 +1,59 @@ +#include "graphicspixmap.h" + +#include +#include +#include +#include + +GraphicsPixmap::GraphicsPixmap() : QGraphicsObject() +{ + setCacheMode(DeviceCoordinateCache); +} + +void GraphicsPixmap::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + QGraphicsObject::mousePressEvent(event); + if (event->button() == Qt::LeftButton) + { + emit clicked(); + } +} + +void GraphicsPixmap::setItemOffset(QPointF ponit) +{ + prepareGeometryChange(); + offset = ponit; + update(); +} + +QPointF GraphicsPixmap::itemoffset() +{ + return offset; +} + +void GraphicsPixmap::setPixmap(const QPixmap& pixmap) +{ + pixSize = pixmap.size(); + pix = pixmap; +} + +void GraphicsPixmap::setPixmapSize(QSize size) +{ + pixSize = size; +} + +QSize GraphicsPixmap::pixsize() +{ + return pixSize; +} + +QRectF GraphicsPixmap::boundingRect() const +{ + return QRectF(offset, pix.size() / pix.devicePixelRatio()); +} + +void GraphicsPixmap::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + painter->setRenderHint(QPainter::SmoothPixmapTransform, true); + painter->drawPixmap(offset, pix.scaled(pixSize, Qt::KeepAspectRatio, Qt::SmoothTransformation)); +} \ No newline at end of file diff --git a/netfriend/imageviewwindow/graphicspixmap.h b/netfriend/imageviewwindow/graphicspixmap.h new file mode 100644 index 0000000..9bf2dad --- /dev/null +++ b/netfriend/imageviewwindow/graphicspixmap.h @@ -0,0 +1,38 @@ +#ifndef GRAPHICSPIXMAP_H +#define GRAPHICSPIXMAP_H + +#include +#include +#include + +class GraphicsPixmap : public QGraphicsObject +{ + Q_OBJECT + Q_PROPERTY(QPointF itemoffset READ itemoffset WRITE setItemOffset) + Q_PROPERTY(QSize itemsize READ pixsize WRITE setPixmapSize) + +public: + GraphicsPixmap(); + +public: + QRectF boundingRect() const Q_DECL_OVERRIDE; + void setItemOffset(QPointF ponit); + QPointF itemoffset(); + QSize pixsize(); + void setPixmap(const QPixmap& pixmap); + void setPixmapSize(QSize size); + +signals: + void clicked(); + +private: + void mousePressEvent(QGraphicsSceneMouseEvent *event) Q_DECL_OVERRIDE; + void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) Q_DECL_OVERRIDE; + +private: + QPixmap pix; + QPointF offset; + QSize pixSize; +}; + +#endif // GRAPHICSPIXMAP_H diff --git a/netfriend/imageviewwindow/graphicsview.cpp b/netfriend/imageviewwindow/graphicsview.cpp new file mode 100644 index 0000000..69c1426 --- /dev/null +++ b/netfriend/imageviewwindow/graphicsview.cpp @@ -0,0 +1,18 @@ +#include "graphicsview.h" + +GraphicsView::GraphicsView(QGraphicsScene *scene) + : QGraphicsView(scene) +{ + +} + +GraphicsView::~GraphicsView() +{ + +} + +void GraphicsView::resizeEvent(QResizeEvent *event) +{ + QGraphicsView::resizeEvent(event); + fitInView(sceneRect(), Qt::KeepAspectRatio); +} \ No newline at end of file diff --git a/netfriend/imageviewwindow/graphicsview.h b/netfriend/imageviewwindow/graphicsview.h new file mode 100644 index 0000000..1e625a8 --- /dev/null +++ b/netfriend/imageviewwindow/graphicsview.h @@ -0,0 +1,18 @@ +#ifndef GRAPHICSVIEW_H +#define GRAPHICSVIEW_H + +#include + +class GraphicsView : public QGraphicsView +{ + Q_OBJECT + +public: + GraphicsView(QGraphicsScene *scene); + ~GraphicsView(); + +protected: + void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; +}; + +#endif // GRAPHICSVIEW_H diff --git a/netfriend/imageviewwindow/imageviewwindow.cpp b/netfriend/imageviewwindow/imageviewwindow.cpp new file mode 100644 index 0000000..6d4c5f5 --- /dev/null +++ b/netfriend/imageviewwindow/imageviewwindow.cpp @@ -0,0 +1,211 @@ +#include "imageviewwindow.h" +#include "graphicsview.h" +#include "graphicspixmap.h" + +#include +#include +#include +#include + +const int image_conunt = 5; +const int image_yoffset = 40; +const int image_xoffset = 60; +ImageViewWindow::ImageViewWindow(QWidget *parent) + : QWidget(parent) + , m_isStart(false) +{ + ui.setupUi(this); + initControl(); +} + +ImageViewWindow::~ImageViewWindow() +{ + +} + +void ImageViewWindow::initControl() +{ + //场景 + m_scene = new QGraphicsScene(QRect(0, 0, 876, 368), this); + //图片信息 + m_imgMapInfolst << QMap{ + { "zIndex" , "1" }, + { "width" , "120" }, + { "height" , "150" }, + { "top" , "71" }, + { "left" , "134" }, + { "opacity" , "0.6" } + }; + m_imgMapInfolst << QMap{ + { "zIndex", "2" }, + { "width", "130" }, + { "height", "170" }, + { "top", "61" }, + { "left", "0" }, + { "opacity", "0.7" } + }; + m_imgMapInfolst << QMap{ + { "zIndex", "3" }, + { "width", "170" }, + { "height", "218" }, + { "top", "37" }, + { "left", "110" }, + { "opacity", "0.8" } + }; + m_imgMapInfolst << QMap{ + { "zIndex", "4" }, + { "width", "224" }, + { "height", "288" }, + { "top", "0" }, + { "left", "262" }, + { "opacity", "1" } + }; + m_imgMapInfolst << QMap{ + { "zIndex", "3" }, + { "width", "170" }, + { "height", "218" }, + { "top", "37" }, + { "left", "468" }, + { "opacity", "0.8" } + }; + m_imgMapInfolst << QMap{ + { "zIndex", "2" }, + { "width", "130" }, + { "height", "170" }, + { "top", "61" }, + { "left", "620" }, + { "opacity", "0.7" } + }; + m_imgMapInfolst << QMap{ + { "zIndex", "1" }, + { "width", "120" }, + { "height", "150" }, + { "top", "71" }, + { "left", "496" }, + { "opacity", "0.6" } + }; + + //场景中添加图片元素 + for (int index = 0; index < m_imgMapInfolst.size(); index++) + { + const auto imageInfoMap = m_imgMapInfolst[index]; + const QString&& centerImg = QString(":/ImageViewWindow/Resources/%1.jpg").arg(index + 1); + const QPixmap&& pixmap = QPixmap(centerImg); + GraphicsPixmap *item = new GraphicsPixmap(); + item->setPixmap(pixmap); + item->setPixmapSize(QSize(imageInfoMap["width"].toInt(), imageInfoMap["height"].toInt())); + item->setItemOffset(QPointF(imageInfoMap["left"].toInt() + image_xoffset, imageInfoMap["top"].toInt() + image_yoffset)); + item->setZValue(imageInfoMap["zIndex"].toInt()); + item->setOpacity(imageInfoMap["opacity"].toFloat()); + m_items << item; + m_scene->addItem(item); + } + + //left button + GraphicsPixmap *leftBtn = new GraphicsPixmap(); + leftBtn->setCursor(QCursor(Qt::PointingHandCursor)); + leftBtn->setPixmap(QPixmap(":/ImageViewWindow/Resources/Wblog_left.png")); + leftBtn->setItemOffset(QPointF(12, image_yoffset + 124)); + leftBtn->setZValue(5); + m_scene->addItem(leftBtn); + connect(leftBtn, SIGNAL(clicked()), this, SLOT(onLeftBtnClicked())); + //right button + GraphicsPixmap *rightBtn = new GraphicsPixmap(); + rightBtn->setCursor(QCursor(Qt::PointingHandCursor)); + rightBtn->setPixmap(QPixmap(":/ImageViewWindow/Resources/Wblog_right.png")); + rightBtn->setItemOffset(QPointF(836, image_yoffset + 124)); + rightBtn->setZValue(5); + m_scene->addItem(rightBtn); + connect(rightBtn, SIGNAL(clicked()), this, SLOT(onRightBtnClicked())); + + //视图 + GraphicsView *view = new GraphicsView(m_scene); + view->setFrameShape(QFrame::NoFrame); + view->setParent(this); + view->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); + view->setBackgroundBrush(QColor(46, 46, 46)); + view->setCacheMode(QGraphicsView::CacheBackground); + view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); + ui.viewlayout->addWidget(view); + + //动画: 大小,位置 + m_group = new QParallelAnimationGroup; + for (int i = 0; i < m_items.count(); ++i) { + QPropertyAnimation *anim = new QPropertyAnimation(m_items[i], "itemoffset"); + QPropertyAnimation *anims = new QPropertyAnimation(m_items[i], "itemsize"); + m_animationMap.insert(m_items[i], anim); + m_animationsMap.insert(m_items[i], anims); + anim->setDuration(1000); + anims->setDuration(1000); + anim->setEasingCurve(QEasingCurve::OutQuad); + anims->setEasingCurve(QEasingCurve::OutQuad); + m_group->addAnimation(anim); + m_group->addAnimation(anims); + } + //定时切换图片 + m_timer = new QTimer(this); + m_timer->setInterval(2000); + connect(m_timer, &QTimer::timeout, [this](){ + nextPlay(); + }); + connect(m_group, &QParallelAnimationGroup::finished, [this](){ + m_isStart = false; + m_timer->start(); + }); + m_timer->start(); +} + +void ImageViewWindow::onLeftBtnClicked() +{ + //鼠标点击的时候,先暂停定时器预览 + m_timer->stop(); + //上一张 + lastPlay(); +} + +void ImageViewWindow::onRightBtnClicked() +{ + //鼠标点击的时候,先暂停定时器预览 + m_timer->stop(); + //下一张 + nextPlay(); +} + +void ImageViewWindow::play() +{ + for (int index = 0; index < m_imgMapInfolst.size(); index++) + { + const auto item = m_items[index]; + QPropertyAnimation *anim = m_animationMap.value(item); + QPropertyAnimation *anims = m_animationsMap.value(item); + const auto imageInfoMap = m_imgMapInfolst[index]; + item->setZValue(imageInfoMap["zIndex"].toInt()); + item->setOpacity(imageInfoMap["opacity"].toFloat()); + QPointF pointf(imageInfoMap["left"].toInt() + image_xoffset, imageInfoMap["top"].toInt() + image_yoffset); + const QString&& centerImg = QString(":/ImageViewWindow/Resources/%1.jpg").arg(index + 1); + anim->setStartValue(item->itemoffset()); + anims->setStartValue(item->pixsize()); + anim->setEndValue(pointf); + anims->setEndValue(QSize(imageInfoMap["width"].toInt(), imageInfoMap["height"].toInt())); + } + m_isStart = true; +} + + +void ImageViewWindow::nextPlay() +{ + m_group->stop(); + auto firstItem = m_items.takeAt(0); + m_items << firstItem; + play(); + m_group->start(); +} + +void ImageViewWindow::lastPlay() +{ + m_group->stop(); + auto lastItem = m_items.takeAt(m_items.size() - 1); + m_items.prepend(lastItem); + play(); + m_group->start(); +} diff --git a/netfriend/imageviewwindow/imageviewwindow.h b/netfriend/imageviewwindow/imageviewwindow.h new file mode 100644 index 0000000..c8f4b7f --- /dev/null +++ b/netfriend/imageviewwindow/imageviewwindow.h @@ -0,0 +1,42 @@ +#ifndef IMAGEVIEWWINDOW_H +#define IMAGEVIEWWINDOW_H + +#include +#include "ui_imageviewwindow.h" + +class QTimer; +class QPropertyAnimation; +class GraphicsPixmap; +class QGraphicsScene; +class QParallelAnimationGroup; +class ImageViewWindow : public QWidget +{ + Q_OBJECT + +public: + ImageViewWindow(QWidget *parent = 0); + ~ImageViewWindow(); + +private: + void initControl(); + void nextPlay(); + void lastPlay(); + void play(); + +private slots: + void onLeftBtnClicked(); + void onRightBtnClicked(); + +private: + Ui::ImageViewWindowClass ui; + QGraphicsScene* m_scene; + QList > m_imgMapInfolst; + QList m_items; + QParallelAnimationGroup *m_group; + QMap m_animationMap; + QMap m_animationsMap; + QTimer* m_timer; + bool m_isStart; +}; + +#endif // IMAGEVIEWWINDOW_H diff --git a/netfriend/imageviewwindow/imageviewwindow.pro b/netfriend/imageviewwindow/imageviewwindow.pro new file mode 100644 index 0000000..86a8890 --- /dev/null +++ b/netfriend/imageviewwindow/imageviewwindow.pro @@ -0,0 +1,20 @@ +QT += core gui +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets +greaterThan(QT_MAJOR_VERSION, 5): QT += core5compat + +TARGET = imageviewwindow +TEMPLATE = app +DESTDIR = $$PWD/../bin +CONFIG += warn_off + +HEADERS += graphicsview.h +HEADERS += graphicspixmap.h +HEADERS += imageviewwindow.h + +SOURCES += main.cpp +SOURCES += graphicspixmap.cpp +SOURCES += graphicsview.cpp +SOURCES += imageviewwindow.cpp + +FORMS += imageviewwindow.ui +RESOURCES += imageviewwindow.qrc diff --git a/netfriend/imageviewwindow/imageviewwindow.qrc b/netfriend/imageviewwindow/imageviewwindow.qrc new file mode 100644 index 0000000..f3ca46d --- /dev/null +++ b/netfriend/imageviewwindow/imageviewwindow.qrc @@ -0,0 +1,13 @@ + + + Resources/1.jpg + Resources/2.jpg + Resources/3.jpg + Resources/4.jpg + Resources/5.jpg + Resources/6.jpg + Resources/7.jpg + Resources/Wblog_left.png + Resources/Wblog_right.png + + diff --git a/netfriend/imageviewwindow/imageviewwindow.ui b/netfriend/imageviewwindow/imageviewwindow.ui new file mode 100644 index 0000000..508ea42 --- /dev/null +++ b/netfriend/imageviewwindow/imageviewwindow.ui @@ -0,0 +1,39 @@ + + + ImageViewWindowClass + + + + 0 + 0 + 1062 + 538 + + + + ImageViewWindow + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + diff --git a/netfriend/imageviewwindow/main.cpp b/netfriend/imageviewwindow/main.cpp new file mode 100644 index 0000000..7290eda --- /dev/null +++ b/netfriend/imageviewwindow/main.cpp @@ -0,0 +1,29 @@ +#pragma execution_character_set("utf-8") + +#include "imageviewwindow.h" +#include +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + a.setFont(QFont("Microsoft Yahei", 9)); + +#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0)) +#if _MSC_VER + QTextCodec *codec = QTextCodec::codecForName("gbk"); +#else + QTextCodec *codec = QTextCodec::codecForName("utf-8"); +#endif + QTextCodec::setCodecForLocale(codec); + QTextCodec::setCodecForCStrings(codec); + QTextCodec::setCodecForTr(codec); +#else + QTextCodec *codec = QTextCodec::codecForName("utf-8"); + QTextCodec::setCodecForLocale(codec); +#endif + + ImageViewWindow w; + w.show(); + return a.exec(); +} diff --git a/netfriend/netfriend.pro b/netfriend/netfriend.pro new file mode 100644 index 0000000..88a605f --- /dev/null +++ b/netfriend/netfriend.pro @@ -0,0 +1,5 @@ +TEMPLATE = subdirs +SUBDIRS += astackwidget +SUBDIRS += imagecropper +SUBDIRS += imageviewwindow +SUBDIRS += slidepuzzlewidget diff --git a/netfriend/slidepuzzlewidget/Resources/back1.png b/netfriend/slidepuzzlewidget/Resources/back1.png new file mode 100644 index 0000000..ff8baa9 Binary files /dev/null and b/netfriend/slidepuzzlewidget/Resources/back1.png differ diff --git a/netfriend/slidepuzzlewidget/Resources/back2.png b/netfriend/slidepuzzlewidget/Resources/back2.png new file mode 100644 index 0000000..203e262 Binary files /dev/null and b/netfriend/slidepuzzlewidget/Resources/back2.png differ diff --git a/netfriend/slidepuzzlewidget/Resources/back3.png b/netfriend/slidepuzzlewidget/Resources/back3.png new file mode 100644 index 0000000..ba3db89 Binary files /dev/null and b/netfriend/slidepuzzlewidget/Resources/back3.png differ diff --git a/netfriend/slidepuzzlewidget/Resources/back4.png b/netfriend/slidepuzzlewidget/Resources/back4.png new file mode 100644 index 0000000..c077c29 Binary files /dev/null and b/netfriend/slidepuzzlewidget/Resources/back4.png differ diff --git a/netfriend/slidepuzzlewidget/frmslidepuzzlewidget.cpp b/netfriend/slidepuzzlewidget/frmslidepuzzlewidget.cpp new file mode 100644 index 0000000..78df26f --- /dev/null +++ b/netfriend/slidepuzzlewidget/frmslidepuzzlewidget.cpp @@ -0,0 +1,18 @@ +#include "frmslidepuzzlewidget.h" + +FrmSlidePuzzleWidget::FrmSlidePuzzleWidget(QWidget *parent) + : QWidget(parent) +{ + ui.setupUi(this); + this->initForm(); +} + +FrmSlidePuzzleWidget::~FrmSlidePuzzleWidget() +{ + +} + +void FrmSlidePuzzleWidget::initForm() +{ + +} diff --git a/netfriend/slidepuzzlewidget/frmslidepuzzlewidget.h b/netfriend/slidepuzzlewidget/frmslidepuzzlewidget.h new file mode 100644 index 0000000..ca15483 --- /dev/null +++ b/netfriend/slidepuzzlewidget/frmslidepuzzlewidget.h @@ -0,0 +1,22 @@ +#ifndef FRMSLIDEPUZZLEWIDGET_H +#define FRMSLIDEPUZZLEWIDGET_H + +#include +#include "ui_frmslidepuzzlewidget.h" + +class FrmSlidePuzzleWidget : public QWidget +{ + Q_OBJECT + +public: + FrmSlidePuzzleWidget(QWidget *parent = 0); + ~FrmSlidePuzzleWidget(); + +private: + void initForm(); + +private: + Ui::FrmSlidePuzzleWidgetClass ui; +}; + +#endif // FRMSLIDEPUZZLEWIDGET_H diff --git a/netfriend/slidepuzzlewidget/frmslidepuzzlewidget.qrc b/netfriend/slidepuzzlewidget/frmslidepuzzlewidget.qrc new file mode 100644 index 0000000..2637c50 --- /dev/null +++ b/netfriend/slidepuzzlewidget/frmslidepuzzlewidget.qrc @@ -0,0 +1,8 @@ + + + Resources/back1.png + Resources/back2.png + Resources/back3.png + Resources/back4.png + + diff --git a/netfriend/slidepuzzlewidget/frmslidepuzzlewidget.ui b/netfriend/slidepuzzlewidget/frmslidepuzzlewidget.ui new file mode 100644 index 0000000..59d1673 --- /dev/null +++ b/netfriend/slidepuzzlewidget/frmslidepuzzlewidget.ui @@ -0,0 +1,50 @@ + + + FrmSlidePuzzleWidgetClass + + + + 0 + 0 + 600 + 400 + + + + FrmSlidePuzzleWidget + + + + 20 + + + 20 + + + 20 + + + 20 + + + 20 + + + + + + + + + + SliderPuzzleWidget + QWidget +
sliderpuzzlewidget.h
+ 1 +
+
+ + + + +
diff --git a/netfriend/slidepuzzlewidget/main.cpp b/netfriend/slidepuzzlewidget/main.cpp new file mode 100644 index 0000000..f88a322 --- /dev/null +++ b/netfriend/slidepuzzlewidget/main.cpp @@ -0,0 +1,30 @@ +#pragma execution_character_set("utf-8") + +#include "frmslidepuzzlewidget.h" +#include +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + a.setFont(QFont("Microsoft Yahei", 10)); + +#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0)) +#if _MSC_VER + QTextCodec *codec = QTextCodec::codecForName("gbk"); +#else + QTextCodec *codec = QTextCodec::codecForName("utf-8"); +#endif + QTextCodec::setCodecForLocale(codec); + QTextCodec::setCodecForCStrings(codec); + QTextCodec::setCodecForTr(codec); +#else + QTextCodec *codec = QTextCodec::codecForName("utf-8"); + QTextCodec::setCodecForLocale(codec); +#endif + + FrmSlidePuzzleWidget w; + w.setWindowTitle("滑块图片验证码"); + w.show(); + return a.exec(); +} diff --git a/netfriend/slidepuzzlewidget/puzzlewidget.cpp b/netfriend/slidepuzzlewidget/puzzlewidget.cpp new file mode 100644 index 0000000..e5c1ecb --- /dev/null +++ b/netfriend/slidepuzzlewidget/puzzlewidget.cpp @@ -0,0 +1,81 @@ +#include "puzzlewidget.h" + +#include +#include +#include +#include + +const int squarewidth = 46; +const int squareradius = 20; +PuzzleWidget::PuzzleWidget(QWidget *parent) + : QWidget(parent) +{ + m_value = 0; + m_offsetPoint = QPoint(0, 0); + srand(QTime(0, 0, 0).secsTo(QTime::currentTime())); +} + +PuzzleWidget::~PuzzleWidget() +{ + +} + +void PuzzleWidget::setPixmap(const QString& pixmap) +{ + m_pixmap = pixmap; + QTimer::singleShot(10, this, SLOT(onUpdatePixmap())); +} + +void PuzzleWidget::onUpdatePixmap() +{ + m_offsetPoint.rx() = qBound(0, rand() % this->width() + squarewidth + squareradius, this->width() - squarewidth - squareradius); + m_offsetPoint.ry() = qBound(0, rand() % this->height() + squarewidth + squareradius, this->height() - squarewidth - squareradius); + update(); +} + +void PuzzleWidget::setValue(int value) +{ + m_value = qBound(0, value, this->width() - squarewidth - squareradius + m_offsetPoint.x()); + update(); +} + +void PuzzleWidget::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + painter.setRenderHints(QPainter::Antialiasing); + QPainterPath clippath; + clippath.addRoundedRect(this->rect(), 4, 4); + painter.setClipPath(clippath); + const QPixmap& pixmap = QPixmap(m_pixmap).scaled(this->width(), this->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + painter.drawPixmap(0, 0, this->width(), this->height(), pixmap); + + QPainterPath cutoutpath; + cutoutpath.setFillRule(Qt::WindingFill); + QRect rect(m_offsetPoint, QSize(squarewidth, squarewidth)); + cutoutpath.addRoundedRect(rect, 2, 2); + cutoutpath.addEllipse(rect.center().x() - squareradius / 2, rect.top() - squareradius + 6, squareradius, squareradius); + QPainterPath subellipseparh; + subellipseparh.addEllipse(rect.right() - squareradius + 6, rect.center().y() - squareradius / 2, squareradius, squareradius); + cutoutpath -= subellipseparh; + + painter.setPen(QPen(QColor(80, 80, 80), 1)); + painter.setBrush(QColor(100, 100, 100, 220)); + painter.drawPath(cutoutpath); + + QPixmap puzzlePixmap(this->size()); + puzzlePixmap.fill(Qt::transparent); + QPainter puzzlePainter(&puzzlePixmap); + puzzlePainter.setRenderHints(QPainter::Antialiasing); + puzzlePainter.setClipPath(cutoutpath); + puzzlePainter.setPen(QPen(QColor(80, 80, 80), 2)); + puzzlePainter.setBrush(QColor(200, 200, 200, 100)); + puzzlePainter.drawPixmap(0, 0, this->width(), this->height(), pixmap); + puzzlePainter.drawPath(cutoutpath); + + painter.drawPixmap(-m_offsetPoint.x() + m_value, 0, this->width(), this->height(), puzzlePixmap); +} + +bool PuzzleWidget::isOverlap() +{ + return qAbs(-m_offsetPoint.x() + m_value) < 5; +} diff --git a/netfriend/slidepuzzlewidget/puzzlewidget.h b/netfriend/slidepuzzlewidget/puzzlewidget.h new file mode 100644 index 0000000..117e717 --- /dev/null +++ b/netfriend/slidepuzzlewidget/puzzlewidget.h @@ -0,0 +1,34 @@ +#ifndef PUZZLEWIDGET_H +#define PUZZLEWIDGET_H + +#include + +class PuzzleWidget : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QString pixmap READ getPixmap WRITE setPixmap) + +public: + PuzzleWidget(QWidget *parent); + ~PuzzleWidget(); + +public: + QString getPixmap() const { return m_pixmap; }; + void setPixmap(const QString& pixmap); + + void setValue(int value); + bool isOverlap(); + +private slots: + void onUpdatePixmap(); + +protected: + void paintEvent(QPaintEvent *event); + +private: + int m_value; + QString m_pixmap; + QPoint m_offsetPoint; +}; + +#endif // PUZZLEWIDGET_H diff --git a/netfriend/slidepuzzlewidget/slidepuzzlewidget.pro b/netfriend/slidepuzzlewidget/slidepuzzlewidget.pro new file mode 100644 index 0000000..234abfe --- /dev/null +++ b/netfriend/slidepuzzlewidget/slidepuzzlewidget.pro @@ -0,0 +1,23 @@ +QT += core gui +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets +greaterThan(QT_MAJOR_VERSION, 5): QT += core5compat + +TEMPLATE = app +TARGET = slidepuzzlewidget +DESTDIR = $$PWD/../bin +CONFIG += warn_off + +HEADERS += frmslidepuzzlewidget.h +HEADERS += puzzlewidget.h +HEADERS += sliderpuzzlewidget.h + +SOURCES += main.cpp +SOURCES += frmslidepuzzlewidget.cpp +SOURCES += puzzlewidget.cpp +SOURCES += sliderpuzzlewidget.cpp + +FORMS += frmslidepuzzlewidget.ui +FORMS += sliderpuzzlewidget.ui +RESOURCES += frmslidepuzzlewidget.qrc + + diff --git a/netfriend/slidepuzzlewidget/sliderpuzzlewidget.cpp b/netfriend/slidepuzzlewidget/sliderpuzzlewidget.cpp new file mode 100644 index 0000000..1d29bb5 --- /dev/null +++ b/netfriend/slidepuzzlewidget/sliderpuzzlewidget.cpp @@ -0,0 +1,49 @@ +#pragma execution_character_set("utf-8") +#include "sliderpuzzlewidget.h" + +#include +#include + +SliderPuzzleWidget::SliderPuzzleWidget(QWidget *parent) + : QWidget(parent) +{ + ui.setupUi(this); + this->initForm(); +} + +SliderPuzzleWidget::~SliderPuzzleWidget() +{ + +} + +void SliderPuzzleWidget::initForm() +{ + QTimer::singleShot(10, this, SLOT(onUpdateWidget())); + connect(ui.horizontalSlider, &QSlider::valueChanged, this, &SliderPuzzleWidget::onSliderValueChanged); + connect(ui.horizontalSlider, &QSlider::sliderReleased, this, &SliderPuzzleWidget::onSliderReleased); + ui.puzzlewidget->setPixmap(":/FrmSlidePuzzleWidget/Resources/back1.png"); +} + +void SliderPuzzleWidget::onUpdateWidget() +{ + ui.horizontalSlider->setRange(0, this->width()); +} + +void SliderPuzzleWidget::onSliderValueChanged(int value) +{ + ui.puzzlewidget->setValue(value); +} + +void SliderPuzzleWidget::onSliderReleased() +{ + QString content = ui.puzzlewidget->isOverlap() ? "验证成功!" : "验证失败!"; + QMessageBox msgBox; + msgBox.setWindowTitle("滑块图片验证码"); + msgBox.setText(content); + msgBox.exec(); + + static int testIndex = 1; + testIndex = testIndex + 1 > 4 ? 1 : testIndex + 1; + ui.horizontalSlider->setValue(0); + ui.puzzlewidget->setPixmap(QString(":/FrmSlidePuzzleWidget/Resources/back%1.png").arg(testIndex)); +} \ No newline at end of file diff --git a/netfriend/slidepuzzlewidget/sliderpuzzlewidget.h b/netfriend/slidepuzzlewidget/sliderpuzzlewidget.h new file mode 100644 index 0000000..3dda2d7 --- /dev/null +++ b/netfriend/slidepuzzlewidget/sliderpuzzlewidget.h @@ -0,0 +1,27 @@ +#ifndef SLIDERPUZZLEWIDGET_H +#define SLIDERPUZZLEWIDGET_H + +#include +#include "ui_sliderpuzzlewidget.h" + +class SliderPuzzleWidget : public QWidget +{ + Q_OBJECT + +public: + SliderPuzzleWidget(QWidget *parent = 0); + ~SliderPuzzleWidget(); + +private: + void initForm(); + +private slots: + void onUpdateWidget(); + void onSliderValueChanged(int value); + void onSliderReleased(); + +private: + Ui::SliderPuzzleWidget ui; +}; + +#endif // SLIDERPUZZLEWIDGET_H diff --git a/netfriend/slidepuzzlewidget/sliderpuzzlewidget.ui b/netfriend/slidepuzzlewidget/sliderpuzzlewidget.ui new file mode 100644 index 0000000..311cb13 --- /dev/null +++ b/netfriend/slidepuzzlewidget/sliderpuzzlewidget.ui @@ -0,0 +1,55 @@ + + + SliderPuzzleWidget + + + + 0 + 0 + 717 + 320 + + + + SliderPuzzleWidget + + + + 14 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + Qt::Horizontal + + + + + + + + + PuzzleWidget + QWidget +
puzzlewidget.h
+ 1 +
+
+ + +