<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
本文介紹利用QDrag類實現拖拽拼圖功能。左邊是打散的圖,拖動到右邊進行復現,此外程式還支援手動拖入原圖片。
新建一個Qt案例,專案名稱為“puzzle”,基礎類別選擇“QMainWindow”,取消選中建立UI介面核取方塊,完成專案建立。
UI介面如下:
無UI介面
原始檔main.cpp中需要預先呼叫loadImage函數載入影象並顯示介面,程式碼如下:
QApplication a(argc, argv); MainWindow w; w.loadImage(QStringLiteral(":/example.jpg")); w.show(); return a.exec();
標頭檔案中宣告相應的物件和槽函數:
public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); void loadImage(const QString &path); public slots: void openImage(); void setupPuzzle(); private slots: void setCompleted(); private: void setupMenus(); void setupWidgets(); QPixmap puzzleImage; PiecesList *piecesList; PuzzleWidget *puzzleWidget;
原始檔中對函數進行定義,首先在建構函式中執行setupMenus()函數和setupWidgets()函數並設定大小尺寸和標題:
setupMenus(); setupWidgets(); setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));//設定大小策略 setWindowTitle(tr("拖拽拼圖"));
定義開啟影象函數:
//開啟影象(重新選擇影象分割) void MainWindow::openImage() { const QString directory = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).value(0, QDir::homePath()); QFileDialog dialog(this, tr("Open Image"), directory);//建立開啟檔案對話方塊 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("拼圖完成"), tr("恭喜!您已經成功拼圖 n" "點選OK重新開始"), 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->width(), puzzleWidget->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);//縮放 piecesList->clear();//清空List //切分成5*5=25張拼圖 for (int y = 0; y < 5; ++y) { for (int x = 0; x < 5; ++x) { int pieceSize = puzzleWidget->pieceSize(); QPixmap pieceImage = puzzleImage.copy(x * pieceSize, y * pieceSize, pieceSize, pieceSize); piecesList->addPiece(pieceImage, QPoint(x, y)); } } for (int i = 0; i < piecesList->count(); ++i) { if (QRandomGenerator::global()->bounded(2) == 1) { QListWidgetItem *item = piecesList->takeItem(i); piecesList->insertItem(0, item); } } puzzleWidget->clear(); }
設定選單欄:
//設定選單欄 void MainWindow::setupMenus() { QMenu *fileMenu = menuBar()->addMenu(tr("&檔案")); QAction *openAction = fileMenu->addAction(tr("&開啟..."), this, &MainWindow::openImage); openAction->setShortcuts(QKeySequence::Open); //快捷鍵 QAction *exitAction = fileMenu->addAction(tr("&退出"), qApp, &QCoreApplication::quit); exitAction->setShortcuts(QKeySequence::Quit); //快捷鍵 QMenu *gameMenu = menuBar()->addMenu(tr("&遊戲")); gameMenu->addAction(tr("&重啟"), this, &MainWindow::setupPuzzle); }
設定介面佈局:
//設定介面佈局 void MainWindow::setupWidgets() { QFrame *frame = new QFrame; QHBoxLayout *frameLayout = new QHBoxLayout(frame);//水平佈局 puzzleWidget = new PuzzleWidget(400);//新建PuzzleWidget物件,設定影象尺寸為400 piecesList = new PiecesList(puzzleWidget->pieceSize(), this); connect(puzzleWidget, &PuzzleWidget::puzzleCompleted, this, &MainWindow::setCompleted, Qt::QueuedConnection); frameLayout->addWidget(piecesList); frameLayout->addWidget(puzzleWidget); setCentralWidget(frame);//中心部件 }
新建PiecesList類,並繼承自QListWidget:
新建PuzzleWidget類,繼承自QWidget:
它實現了以下幾個方法。
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;
Drag執行的流程是:
Drag是從drag->exec()開始的,此時將開啟進入一個新的事件迴圈,然後在拖動的過程中會在下面三個事件中交替:
其中DragEnter是有拖動進入該Widget時觸發的,對應的DragLeave則是拖動離開時觸發的,而DragMove就是滑鼠拖動的時候觸發的。
最後當滑鼠釋放的時候將觸發dragEvent,此時將決定拖拽的結果。
回頭看一下Drag的觸發,和大多數系統一樣,一個Drag可能是從控制元件外觸發的,即將外部的資料拖入,也可以是從控制元件內部觸發,即手動生成一個QDrag物件。
拖動的機制:
其實拖動就是將一處的資料移動或者複製到另外一處,在QT中拖動所承載的資料使用QMimeData表示的,它可以用來表示許多Mime Type的集合。一個Mime Type即有format和data兩部分組成,format即指示瞭如何解析對應的data。
完整效果如下:
初始介面:
拼圖完成後介面:
到此這篇關於Qt利用QDrag實現拖拽拼圖功能詳解的文章就介紹到這了,更多相關Qt QDrag拖拽拼圖內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45