mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-07-05 00:35:27 +08:00
qt 6.5.1 original
This commit is contained in:
51
examples/widgets/itemviews/puzzle/CMakeLists.txt
Normal file
51
examples/widgets/itemviews/puzzle/CMakeLists.txt
Normal file
@ -0,0 +1,51 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(puzzle LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/puzzle")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(itemviews_puzzle
|
||||
main.cpp
|
||||
mainwindow.cpp mainwindow.h
|
||||
piecesmodel.cpp piecesmodel.h
|
||||
puzzlewidget.cpp puzzlewidget.h
|
||||
)
|
||||
|
||||
set_target_properties(itemviews_puzzle PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(itemviews_puzzle PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
# Resources:
|
||||
set(puzzle_resource_files
|
||||
"example.jpg"
|
||||
)
|
||||
|
||||
qt_add_resources(itemviews_puzzle "puzzle"
|
||||
PREFIX
|
||||
"/images"
|
||||
FILES
|
||||
${puzzle_resource_files}
|
||||
)
|
||||
|
||||
install(TARGETS itemviews_puzzle
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
BIN
examples/widgets/itemviews/puzzle/example.jpg
Normal file
BIN
examples/widgets/itemviews/puzzle/example.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
17
examples/widgets/itemviews/puzzle/main.cpp
Normal file
17
examples/widgets/itemviews/puzzle/main.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Q_INIT_RESOURCE(puzzle);
|
||||
|
||||
QApplication app(argc, argv);
|
||||
MainWindow window;
|
||||
window.loadImage(QStringLiteral(":/images/example.jpg"));
|
||||
window.show();
|
||||
return app.exec();
|
||||
}
|
115
examples/widgets/itemviews/puzzle/mainwindow.cpp
Normal file
115
examples/widgets/itemviews/puzzle/mainwindow.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "piecesmodel.h"
|
||||
#include "puzzlewidget.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
#include <stdlib.h>
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
{
|
||||
setupMenus();
|
||||
setupWidgets();
|
||||
model = new PiecesModel(puzzleWidget->pieceSize(), this);
|
||||
piecesList->setModel(model);
|
||||
|
||||
setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
|
||||
setWindowTitle(tr("Puzzle"));
|
||||
}
|
||||
|
||||
void MainWindow::openImage()
|
||||
{
|
||||
const QString directory =
|
||||
QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).value(0, QDir::homePath());
|
||||
QFileDialog dialog(this, tr("Open Image"), directory);
|
||||
dialog.setAcceptMode(QFileDialog::AcceptOpen);
|
||||
dialog.setFileMode(QFileDialog::ExistingFile);
|
||||
QStringList mimeTypeFilters;
|
||||
for (const QByteArray &mimeTypeName : QImageReader::supportedMimeTypes())
|
||||
mimeTypeFilters.append(mimeTypeName);
|
||||
mimeTypeFilters.sort();
|
||||
dialog.setMimeTypeFilters(mimeTypeFilters);
|
||||
dialog.selectMimeTypeFilter("image/jpeg");
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
loadImage(dialog.selectedFiles().constFirst());
|
||||
}
|
||||
|
||||
void MainWindow::loadImage(const QString &fileName)
|
||||
{
|
||||
QPixmap newImage;
|
||||
if (!newImage.load(fileName)) {
|
||||
QMessageBox::warning(this, tr("Open Image"),
|
||||
tr("The image file could not be loaded."),
|
||||
QMessageBox::Close);
|
||||
return;
|
||||
}
|
||||
puzzleImage = newImage;
|
||||
setupPuzzle();
|
||||
}
|
||||
|
||||
void MainWindow::setCompleted()
|
||||
{
|
||||
QMessageBox::information(this, tr("Puzzle Completed"),
|
||||
tr("Congratulations! You have completed the puzzle!\n"
|
||||
"Click OK to start again."),
|
||||
QMessageBox::Ok);
|
||||
|
||||
setupPuzzle();
|
||||
}
|
||||
|
||||
void MainWindow::setupPuzzle()
|
||||
{
|
||||
int size = qMin(puzzleImage.width(), puzzleImage.height());
|
||||
puzzleImage = puzzleImage.copy((puzzleImage.width() - size) / 2,
|
||||
(puzzleImage.height() - size) / 2, size, size).scaled(puzzleWidget->imageSize(),
|
||||
puzzleWidget->imageSize(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
|
||||
model->addPieces(puzzleImage);
|
||||
puzzleWidget->clear();
|
||||
}
|
||||
|
||||
void MainWindow::setupMenus()
|
||||
{
|
||||
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
|
||||
|
||||
QAction *openAction = fileMenu->addAction(tr("&Open..."), this, &MainWindow::openImage);
|
||||
openAction->setShortcuts(QKeySequence::Open);
|
||||
|
||||
QAction *exitAction = fileMenu->addAction(tr("E&xit"), qApp, &QCoreApplication::quit);
|
||||
exitAction->setShortcuts(QKeySequence::Quit);
|
||||
|
||||
QMenu *gameMenu = menuBar()->addMenu(tr("&Game"));
|
||||
|
||||
gameMenu->addAction(tr("&Restart"), this, &MainWindow::setupPuzzle);
|
||||
}
|
||||
|
||||
void MainWindow::setupWidgets()
|
||||
{
|
||||
QFrame *frame = new QFrame;
|
||||
QHBoxLayout *frameLayout = new QHBoxLayout(frame);
|
||||
|
||||
puzzleWidget = new PuzzleWidget(400);
|
||||
|
||||
piecesList = new QListView;
|
||||
piecesList->setDragEnabled(true);
|
||||
piecesList->setViewMode(QListView::IconMode);
|
||||
piecesList->setIconSize(QSize(puzzleWidget->pieceSize() - 20, puzzleWidget->pieceSize() - 20));
|
||||
piecesList->setGridSize(QSize(puzzleWidget->pieceSize(), puzzleWidget->pieceSize()));
|
||||
piecesList->setSpacing(10);
|
||||
piecesList->setMovement(QListView::Snap);
|
||||
piecesList->setAcceptDrops(true);
|
||||
piecesList->setDropIndicatorShown(true);
|
||||
|
||||
PiecesModel *model = new PiecesModel(puzzleWidget->pieceSize(), this);
|
||||
piecesList->setModel(model);
|
||||
|
||||
connect(puzzleWidget, &PuzzleWidget::puzzleCompleted,
|
||||
this, &MainWindow::setCompleted, Qt::QueuedConnection);
|
||||
|
||||
frameLayout->addWidget(piecesList);
|
||||
frameLayout->addWidget(puzzleWidget);
|
||||
setCentralWidget(frame);
|
||||
}
|
41
examples/widgets/itemviews/puzzle/mainwindow.h
Normal file
41
examples/widgets/itemviews/puzzle/mainwindow.h
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QPixmap>
|
||||
|
||||
class PuzzleWidget;
|
||||
class PiecesModel;
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QListView;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void openImage();
|
||||
void loadImage(const QString &path);
|
||||
void setupPuzzle();
|
||||
|
||||
private slots:
|
||||
void setCompleted();
|
||||
|
||||
private:
|
||||
void setupMenus();
|
||||
void setupWidgets();
|
||||
|
||||
QPixmap puzzleImage;
|
||||
QListView *piecesList;
|
||||
PuzzleWidget *puzzleWidget;
|
||||
PiecesModel *model;
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
168
examples/widgets/itemviews/puzzle/piecesmodel.cpp
Normal file
168
examples/widgets/itemviews/puzzle/piecesmodel.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "piecesmodel.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QMimeData>
|
||||
#include <QRandomGenerator>
|
||||
|
||||
PiecesModel::PiecesModel(int pieceSize, QObject *parent)
|
||||
: QAbstractListModel(parent), m_PieceSize(pieceSize)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant PiecesModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
if (role == Qt::DecorationRole)
|
||||
return QIcon(pixmaps.value(index.row()).scaled(m_PieceSize, m_PieceSize,
|
||||
Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
else if (role == Qt::UserRole)
|
||||
return pixmaps.value(index.row());
|
||||
else if (role == Qt::UserRole + 1)
|
||||
return locations.value(index.row());
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void PiecesModel::addPiece(const QPixmap &pixmap, const QPoint &location)
|
||||
{
|
||||
int row;
|
||||
if (QRandomGenerator::global()->bounded(2) == 1)
|
||||
row = 0;
|
||||
else
|
||||
row = pixmaps.size();
|
||||
|
||||
beginInsertRows(QModelIndex(), row, row);
|
||||
pixmaps.insert(row, pixmap);
|
||||
locations.insert(row, location);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
Qt::ItemFlags PiecesModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (index.isValid())
|
||||
return (QAbstractListModel::flags(index)|Qt::ItemIsDragEnabled);
|
||||
|
||||
return Qt::ItemIsDropEnabled;
|
||||
}
|
||||
|
||||
bool PiecesModel::removeRows(int row, int count, const QModelIndex &parent)
|
||||
{
|
||||
if (parent.isValid())
|
||||
return false;
|
||||
|
||||
if (row >= pixmaps.size() || row + count <= 0)
|
||||
return false;
|
||||
|
||||
int beginRow = qMax(0, row);
|
||||
int endRow = qMin(row + count - 1, pixmaps.size() - 1);
|
||||
|
||||
beginRemoveRows(parent, beginRow, endRow);
|
||||
|
||||
while (beginRow <= endRow) {
|
||||
pixmaps.removeAt(beginRow);
|
||||
locations.removeAt(beginRow);
|
||||
++beginRow;
|
||||
}
|
||||
|
||||
endRemoveRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
QStringList PiecesModel::mimeTypes() const
|
||||
{
|
||||
QStringList types;
|
||||
types << "image/x-puzzle-piece";
|
||||
return types;
|
||||
}
|
||||
|
||||
QMimeData *PiecesModel::mimeData(const QModelIndexList &indexes) const
|
||||
{
|
||||
QMimeData *mimeData = new QMimeData();
|
||||
QByteArray encodedData;
|
||||
|
||||
QDataStream stream(&encodedData, QDataStream::WriteOnly);
|
||||
|
||||
for (const QModelIndex &index : indexes) {
|
||||
if (index.isValid()) {
|
||||
QPixmap pixmap = qvariant_cast<QPixmap>(data(index, Qt::UserRole));
|
||||
QPoint location = data(index, Qt::UserRole+1).toPoint();
|
||||
stream << pixmap << location;
|
||||
}
|
||||
}
|
||||
|
||||
mimeData->setData("image/x-puzzle-piece", encodedData);
|
||||
return mimeData;
|
||||
}
|
||||
|
||||
bool PiecesModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
|
||||
int row, int column, const QModelIndex &parent)
|
||||
{
|
||||
if (!data->hasFormat("image/x-puzzle-piece"))
|
||||
return false;
|
||||
|
||||
if (action == Qt::IgnoreAction)
|
||||
return true;
|
||||
|
||||
if (column > 0)
|
||||
return false;
|
||||
|
||||
int endRow;
|
||||
|
||||
if (!parent.isValid()) {
|
||||
if (row < 0)
|
||||
endRow = pixmaps.size();
|
||||
else
|
||||
endRow = qMin(row, pixmaps.size());
|
||||
} else {
|
||||
endRow = parent.row();
|
||||
}
|
||||
|
||||
QByteArray encodedData = data->data("image/x-puzzle-piece");
|
||||
QDataStream stream(&encodedData, QDataStream::ReadOnly);
|
||||
|
||||
while (!stream.atEnd()) {
|
||||
QPixmap pixmap;
|
||||
QPoint location;
|
||||
stream >> pixmap >> location;
|
||||
|
||||
beginInsertRows(QModelIndex(), endRow, endRow);
|
||||
pixmaps.insert(endRow, pixmap);
|
||||
locations.insert(endRow, location);
|
||||
endInsertRows();
|
||||
|
||||
++endRow;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int PiecesModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : pixmaps.size();
|
||||
}
|
||||
|
||||
Qt::DropActions PiecesModel::supportedDropActions() const
|
||||
{
|
||||
return Qt::CopyAction | Qt::MoveAction;
|
||||
}
|
||||
|
||||
void PiecesModel::addPieces(const QPixmap &pixmap)
|
||||
{
|
||||
if (!pixmaps.isEmpty()) {
|
||||
beginRemoveRows(QModelIndex(), 0, pixmaps.size() - 1);
|
||||
pixmaps.clear();
|
||||
locations.clear();
|
||||
endRemoveRows();
|
||||
}
|
||||
for (int y = 0; y < 5; ++y) {
|
||||
for (int x = 0; x < 5; ++x) {
|
||||
QPixmap pieceImage = pixmap.copy(x*m_PieceSize, y*m_PieceSize, m_PieceSize, m_PieceSize);
|
||||
addPiece(pieceImage, QPoint(x, y));
|
||||
}
|
||||
}
|
||||
}
|
45
examples/widgets/itemviews/puzzle/piecesmodel.h
Normal file
45
examples/widgets/itemviews/puzzle/piecesmodel.h
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef PIECESLIST_H
|
||||
#define PIECESLIST_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QPixmap>
|
||||
#include <QPoint>
|
||||
#include <QStringList>
|
||||
#include <QList>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QMimeData;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class PiecesModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PiecesModel(int pieceSize, QObject *parent = nullptr);
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
bool removeRows(int row, int count, const QModelIndex &parent) override;
|
||||
|
||||
bool dropMimeData(const QMimeData *data, Qt::DropAction action,
|
||||
int row, int column, const QModelIndex &parent) override;
|
||||
QMimeData *mimeData(const QModelIndexList &indexes) const override;
|
||||
QStringList mimeTypes() const override;
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
Qt::DropActions supportedDropActions() const override;
|
||||
|
||||
void addPiece(const QPixmap &pixmap, const QPoint &location);
|
||||
void addPieces(const QPixmap &pixmap);
|
||||
|
||||
private:
|
||||
QList<QPoint> locations;
|
||||
QList<QPixmap> pixmaps;
|
||||
|
||||
int m_PieceSize;
|
||||
};
|
||||
|
||||
#endif // PIECESLIST_H
|
15
examples/widgets/itemviews/puzzle/puzzle.pro
Normal file
15
examples/widgets/itemviews/puzzle/puzzle.pro
Normal file
@ -0,0 +1,15 @@
|
||||
QT += widgets
|
||||
requires(qtConfig(listview))
|
||||
|
||||
HEADERS = mainwindow.h \
|
||||
piecesmodel.h \
|
||||
puzzlewidget.h
|
||||
RESOURCES = puzzle.qrc
|
||||
SOURCES = main.cpp \
|
||||
mainwindow.cpp \
|
||||
piecesmodel.cpp \
|
||||
puzzlewidget.cpp
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/puzzle
|
||||
INSTALLS += target
|
5
examples/widgets/itemviews/puzzle/puzzle.qrc
Normal file
5
examples/widgets/itemviews/puzzle/puzzle.qrc
Normal file
@ -0,0 +1,5 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource prefix="/images">
|
||||
<file>example.jpg</file>
|
||||
</qresource>
|
||||
</RCC>
|
163
examples/widgets/itemviews/puzzle/puzzlewidget.cpp
Normal file
163
examples/widgets/itemviews/puzzle/puzzlewidget.cpp
Normal file
@ -0,0 +1,163 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "puzzlewidget.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
PuzzleWidget::PuzzleWidget(int imageSize, QWidget *parent)
|
||||
: QWidget(parent), m_ImageSize(imageSize)
|
||||
{
|
||||
setAcceptDrops(true);
|
||||
setMinimumSize(m_ImageSize, m_ImageSize);
|
||||
setMaximumSize(m_ImageSize, m_ImageSize);
|
||||
}
|
||||
|
||||
void PuzzleWidget::clear()
|
||||
{
|
||||
pieces.clear();
|
||||
highlightedRect = QRect();
|
||||
inPlace = 0;
|
||||
update();
|
||||
}
|
||||
|
||||
void PuzzleWidget::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
if (event->mimeData()->hasFormat("image/x-puzzle-piece"))
|
||||
event->accept();
|
||||
else
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
void PuzzleWidget::dragLeaveEvent(QDragLeaveEvent *event)
|
||||
{
|
||||
QRect updateRect = highlightedRect;
|
||||
highlightedRect = QRect();
|
||||
update(updateRect);
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void PuzzleWidget::dragMoveEvent(QDragMoveEvent *event)
|
||||
{
|
||||
QRect updateRect = highlightedRect.united(targetSquare(event->position().toPoint()));
|
||||
|
||||
if (event->mimeData()->hasFormat("image/x-puzzle-piece")
|
||||
&& findPiece(targetSquare(event->position().toPoint())) == -1) {
|
||||
|
||||
highlightedRect = targetSquare(event->position().toPoint());
|
||||
event->setDropAction(Qt::MoveAction);
|
||||
event->accept();
|
||||
} else {
|
||||
highlightedRect = QRect();
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
update(updateRect);
|
||||
}
|
||||
|
||||
void PuzzleWidget::dropEvent(QDropEvent *event)
|
||||
{
|
||||
if (event->mimeData()->hasFormat("image/x-puzzle-piece")
|
||||
&& findPiece(targetSquare(event->position().toPoint())) == -1) {
|
||||
|
||||
QByteArray pieceData = event->mimeData()->data("image/x-puzzle-piece");
|
||||
QDataStream dataStream(&pieceData, QIODevice::ReadOnly);
|
||||
Piece piece;
|
||||
piece.rect = targetSquare(event->position().toPoint());
|
||||
dataStream >> piece.pixmap >> piece.location;
|
||||
|
||||
pieces.append(piece);
|
||||
|
||||
highlightedRect = QRect();
|
||||
update(piece.rect);
|
||||
|
||||
event->setDropAction(Qt::MoveAction);
|
||||
event->accept();
|
||||
|
||||
if (piece.location == piece.rect.topLeft() / pieceSize()) {
|
||||
inPlace++;
|
||||
if (inPlace == 25)
|
||||
emit puzzleCompleted();
|
||||
}
|
||||
} else {
|
||||
highlightedRect = QRect();
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
int PuzzleWidget::findPiece(const QRect &pieceRect) const
|
||||
{
|
||||
for (int i = 0, size = pieces.size(); i < size; ++i) {
|
||||
if (pieces.at(i).rect == pieceRect)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void PuzzleWidget::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
QRect square = targetSquare(event->position().toPoint());
|
||||
int found = findPiece(square);
|
||||
|
||||
if (found == -1)
|
||||
return;
|
||||
|
||||
Piece piece = pieces.takeAt(found);
|
||||
|
||||
if (piece.location == square.topLeft() / pieceSize())
|
||||
inPlace--;
|
||||
|
||||
update(square);
|
||||
|
||||
QByteArray itemData;
|
||||
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
|
||||
|
||||
dataStream << piece.pixmap << piece.location;
|
||||
|
||||
QMimeData *mimeData = new QMimeData;
|
||||
mimeData->setData("image/x-puzzle-piece", itemData);
|
||||
|
||||
QDrag *drag = new QDrag(this);
|
||||
drag->setMimeData(mimeData);
|
||||
drag->setHotSpot(event->position().toPoint() - square.topLeft());
|
||||
drag->setPixmap(piece.pixmap);
|
||||
|
||||
if (drag->exec(Qt::MoveAction) == Qt::IgnoreAction) {
|
||||
pieces.insert(found, piece);
|
||||
update(targetSquare(event->position().toPoint()));
|
||||
|
||||
if (piece.location == QPoint(square.x() / pieceSize(), square.y() / pieceSize()))
|
||||
inPlace++;
|
||||
}
|
||||
}
|
||||
|
||||
void PuzzleWidget::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.fillRect(event->rect(), Qt::white);
|
||||
|
||||
if (highlightedRect.isValid()) {
|
||||
painter.setBrush(QColor("#ffcccc"));
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.drawRect(highlightedRect.adjusted(0, 0, -1, -1));
|
||||
}
|
||||
|
||||
for (const Piece &piece : pieces)
|
||||
painter.drawPixmap(piece.rect, piece.pixmap);
|
||||
}
|
||||
|
||||
const QRect PuzzleWidget::targetSquare(const QPoint &position) const
|
||||
{
|
||||
QPoint topLeft = QPoint(position.x() / pieceSize(), position.y() / pieceSize()) * pieceSize();
|
||||
return QRect(topLeft, QSize(pieceSize(), pieceSize()));
|
||||
}
|
||||
|
||||
int PuzzleWidget::pieceSize() const
|
||||
{
|
||||
return m_ImageSize / 5;
|
||||
}
|
||||
|
||||
int PuzzleWidget::imageSize() const
|
||||
{
|
||||
return m_ImageSize;
|
||||
}
|
56
examples/widgets/itemviews/puzzle/puzzlewidget.h
Normal file
56
examples/widgets/itemviews/puzzle/puzzlewidget.h
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef PUZZLEWIDGET_H
|
||||
#define PUZZLEWIDGET_H
|
||||
|
||||
#include <QPoint>
|
||||
#include <QPixmap>
|
||||
#include <QList>
|
||||
#include <QWidget>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QDragEnterEvent;
|
||||
class QDropEvent;
|
||||
class QMouseEvent;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class PuzzleWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PuzzleWidget(int imageSize, QWidget *parent = nullptr);
|
||||
void clear();
|
||||
|
||||
int pieceSize() const;
|
||||
int imageSize() const;
|
||||
|
||||
signals:
|
||||
void puzzleCompleted();
|
||||
|
||||
protected:
|
||||
void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
void dragLeaveEvent(QDragLeaveEvent *event) override;
|
||||
void dragMoveEvent(QDragMoveEvent *event) override;
|
||||
void dropEvent(QDropEvent *event) override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
struct Piece {
|
||||
QPixmap pixmap;
|
||||
QRect rect;
|
||||
QPoint location;
|
||||
};
|
||||
|
||||
int findPiece(const QRect &pieceRect) const;
|
||||
const QRect targetSquare(const QPoint &position) const;
|
||||
|
||||
QList<Piece> pieces;
|
||||
QRect highlightedRect;
|
||||
int inPlace;
|
||||
int m_ImageSize;
|
||||
};
|
||||
|
||||
#endif // PUZZLEWIDGET_H
|
Reference in New Issue
Block a user