PyQt5 Demo
PyQt 模拟时钟 AnalogClock:
from PyQt5 import QtGui, QtCore from PyQt5.QtCore import Qt from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QApplication,QWidget,QLabel class AnalogClock(QWidget): hourHand = QtGui.QPolygon([ QtCore.QPoint(10, 8), QtCore.QPoint(-10, 8), QtCore.QPoint(0, -60) ]) minuteHand = QtGui.QPolygon([ QtCore.QPoint(8, 8), QtCore.QPoint(-8, 8), QtCore.QPoint(0, -70) ]) secondHand = QtGui.QPolygon([ QtCore.QPoint(4, 8), QtCore.QPoint(-4, 8), QtCore.QPoint(0, -90) ]) hourColor = QtGui.QColor(255, 0, 0) minuteColor = QtGui.QColor(0, 255, 0) secondColor = QtGui.QColor(0, 0, 255) def __init__(self): super().__init__() timer = QtCore.QTimer(self) timer.timeout.connect(self.update) timer.start(1000) self.setWindowTitle("Analog Clock") self.resize(200, 200) def paintEvent(self, event): side = min(self.width(), self.height()) # 最小边 time = QtCore.QTime.currentTime() # 获取系统当前时间 painter = QtGui.QPainter(self) painter.setRenderHint(QtGui.QPainter.Antialiasing) # 抗锯齿 painter.translate(self.width() / 2, self.height() / 2) # 坐标位置 painter.scale(side / 300.0, side / 300.0) # 缩放时 的比例 painter.setPen(QtGui.QColor(0, 0, 0)) painter.drawEllipse(-100, -100, 200, 200) # 画圆。参数是外接矩形左上点和长宽 # painter.drawEllipse(-10,-10,20,20) painter.setPen(AnalogClock.hourColor) for i in range(12): # 整点刻度 painter.drawLine(88, 0, 96, 0) painter.rotate(30.0) painter.setPen(AnalogClock.minuteColor) for j in range(60): # 小刻度 if (j % 5) != 0: painter.drawLine(92, 0, 96, 0) painter.rotate(6.0) painter.setPen(QtCore.Qt.NoPen) painter.setBrush(AnalogClock.hourColor) painter.save() painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0))) painter.drawConvexPolygon(AnalogClock.hourHand) # 画三角形 painter.restore() painter.setPen(QtCore.Qt.NoPen) painter.setBrush(AnalogClock.minuteColor) painter.save() painter.rotate(6.0 * (time.minute() + time.second() / 60.0)) painter.drawConvexPolygon(AnalogClock.minuteHand) painter.restore() painter.setPen(QtCore.Qt.NoPen) painter.setBrush(AnalogClock.secondColor) painter.save() painter.rotate(6.0 * time.second()) painter.drawConvexPolygon(AnalogClock.secondHand) painter.restore() painter.setPen(QtGui.QColor(0, 0, 0)) painter.drawEllipse(-5, -5, 10, 10) # 画圆。参数是外接矩形左上点和长宽 if __name__ == '__main__': import sys app = QApplication(sys.argv) # widget = QWidget() # widget.setWindowTitle("Hello ZCB") # widget.setWindowIcon(QIcon("d:/0.jpg")) # widget.show() clock = AnalogClock() clock.show() sys.exit(app.exec())
通过继承QWidget,并重写父类方法 printEvent() 来实现,1s 更新一次!!!
效果图:
Qt 中的拖拽 QDrag
PyQt Draggable Icons Example
import sys from PyQt5 import QtGui from PyQt5.QtCore import Qt, QByteArray, QDataStream, QIODevice, QPoint, QMimeData, QObject from PyQt5.QtGui import QPixmap, QDrag, QPainter, QColor from PyQt5.QtWidgets import QFrame, QLabel, QApplication, QWidget, QHBoxLayout class DragWidget(QFrame): def __init__(self,parent=None): super().__init__(parent) self.setMinimumSize(200,200) self.setFrameStyle(QFrame.Sunken|QFrame.StyledPanel) self.setAcceptDrops(True) boatIcon = QLabel(self) boatIcon.setPixmap(QPixmap("images/boat.png")) boatIcon.move(10,10) boatIcon.show() boatIcon.setAttribute(Qt.WA_DeleteOnClose) carIcon = QLabel(self) carIcon.setPixmap(QPixmap("images/car.png")) carIcon.move(100,10) carIcon.show() carIcon.setAttribute(Qt.WA_DeleteOnClose) houseIcon = QLabel(self) houseIcon.setPixmap(QPixmap("images/house.png")) houseIcon.move(10,80) houseIcon.show() houseIcon.setAttribute(Qt.WA_DeleteOnClose) def dragEnterEvent(self, evt: QtGui.QDragEnterEvent) -> None: print("drag enter") if evt.mimeData().hasFormat("application/x-zcb"): if evt.source() == self: evt.setDropAction(Qt.MoveAction) evt.accept() else: evt.acceptProposedAction() else: evt.ignore() def dragMoveEvent(self, evt: QtGui.QDragMoveEvent) -> None: print("drag move") if evt.mimeData().hasFormat("application/x-zcb"): if evt.source() == self: evt.setDropAction(Qt.MoveAction) evt.accept() else: evt.acceptProposedAction() else: evt.ignore() def dropEvent(self, evt: QtGui.QDropEvent) -> None: print("drop event") if evt.mimeData().hasFormat("application/x-zcb"): itemData = evt.mimeData().data("application/x-zcb") dataStream = QDataStream(itemData, QIODevice.ReadOnly) pixmap = QPixmap() offset = QPoint() dataStream >> pixmap >> offset newIcon = QLabel(self) newIcon.setPixmap(pixmap) newIcon.move(evt.pos() - offset) newIcon.show() newIcon.setAttribute(Qt.WA_DeleteOnClose) if evt.source() == self: evt.setDropAction(Qt.MoveAction) evt.accept() else: evt.acceptProposedAction() else: evt.ignore() def mousePressEvent(self, evt: QtGui.QMouseEvent) -> None: child:QLabel = self.childAt(evt.pos()) if not child: return pixmap = QPixmap(child.pixmap()) itemData = QByteArray() dataStream = QDataStream(itemData,QIODevice.WriteOnly) dataStream << pixmap <<QPoint(evt.pos() - child.pos()) mimeData = QMimeData() mimeData.setData("application/x-zcb",itemData) drag = QDrag(self) drag.setMimeData(mimeData) drag.setPixmap(pixmap) drag.setHotSpot(evt.pos() - child.pos()) tempPixmap = pixmap painter = QPainter() painter.begin(tempPixmap) painter.fillRect(pixmap.rect(),QColor(127,127,127,255//3)) painter.end() child.setPixmap(tempPixmap) if drag.exec(Qt.CopyAction | Qt.MoveAction, Qt.CopyAction) == Qt.MoveAction: child.close() else: child.show() child.setPixmap(pixmap) if __name__ == '__main__': app = QApplication(sys.argv) mainWidget = QWidget() horLayout = QHBoxLayout() horLayout.addWidget(DragWidget()) horLayout.addWidget(DragWidget()) mainWidget.setLayout(horLayout) mainWidget.setWindowTitle("Draggable Icons") mainWidget.show() app.exec()
https://doc.qt.io/archives/qt-5.5/qtwidgets-draganddrop-draggableicons-example.html
效果图:
PyQt Draggable Text Example
import re import sys from PyQt5 import QtGui from PyQt5.QtCore import Qt, QByteArray, QIODevice, QPoint, QMimeData, QObject, QFile, QTextStream, QRegularExpression from PyQt5.QtGui import QPixmap, QDrag, QPainter, QColor from PyQt5.QtWidgets import QFrame, QLabel, QApplication, QWidget, QHBoxLayout def createDragLabel(text, parent): label = QLabel(text, parent) label.setAutoFillBackground(True) label.setFrameShape(QFrame.Panel) label.setFrameShadow(QFrame.Raised) return label class DragWidget(QWidget): def __init__(self, parent=None): super().__init__(parent) dicFile = QFile("d:/words.txt") dicFile.open(QIODevice.ReadOnly) inputStream = QTextStream(dicFile) x, y = 5, 5 while not inputStream.atEnd(): word = inputStream.readLine() if word: wordLabel: QLabel = createDragLabel(word, self) wordLabel.move(x, y) wordLabel.show() wordLabel.setAttribute(Qt.WA_DeleteOnClose) x += wordLabel.width() + 2 if x >= 245: x = 5 y += wordLabel.height() + 2 self.setAcceptDrops(True) self.setMinimumSize(400, max(200, y)) self.setWindowTitle("Draggable Text") def dragEnterEvent(self, evt: QtGui.QDragEnterEvent) -> None: if evt.mimeData().hasText(): if evt.source() == self: evt.setDropAction(Qt.MoveAction) evt.accept() else: evt.acceptProposedAction() else: evt.ignore() def dropEvent(self, evt: QtGui.QDragMoveEvent) -> None: if evt.mimeData().hasText(): mime = evt.mimeData() pieces = re.split("\s+", mime.text()) position: QPoint = evt.pos() hotSpot = QPoint() hotSpotPos = mime.data("application/x-zcb").split(" ") if len(hotSpotPos) == 2: hotSpot.setX(int(hotSpotPos[0])) hotSpot.setY(int(hotSpotPos[1])) for piece in pieces: newLabel = createDragLabel(piece, self) newLabel.move(position - hotSpot) newLabel.show() newLabel.setAttribute(Qt.WA_DeleteOnClose) position += QPoint(newLabel.width(), 0) if evt.source() == self: evt.setDropAction(Qt.MoveAction) evt.accept() else: evt.acceptProposedAction() else: evt.ignore() def mousePressEvent(self, evt: QtGui.QMouseEvent) -> None: child: QLabel = self.childAt(evt.pos()) if not child: return hotSpot: QPoint = evt.pos() - child.pos() mimeData = QMimeData() mimeData.setText(child.text()) mimeData.setData("application/x-zcb", f"{hotSpot.x()} {hotSpot.y()}".encode()) dpr = self.windowHandle().devicePixelRatio() pixmap = QPixmap(child.size() * dpr) pixmap.setDevicePixelRatio(dpr) child.render(pixmap) drag = QDrag(self) drag.setMimeData(mimeData) drag.setPixmap(pixmap) drag.setHotSpot(hotSpot) dropAction: Qt.DropAction = drag.exec(Qt.CopyAction | Qt.MoveAction, Qt.CopyAction) if dropAction == Qt.MoveAction: child.close() if __name__ == '__main__': app = QApplication(sys.argv) window = DragWidget() window.show() app.exec()
https://doc.qt.io/qt-5/qtwidgets-draganddrop-draggabletext-example.html
效果图:
PyQt Draggable Drop Site Example
https://doc.qt.io/qt-5/qtwidgets-draganddrop-dropsite-example.html
import re import sys from PyQt5 import QtGui from PyQt5.QtCore import Qt, QByteArray, QIODevice, QPoint, QMimeData, QObject, QFile, QTextStream, QRegularExpression, \ pyqtSignal from PyQt5.QtGui import QPixmap, QDrag, QPainter, QColor, QPalette, QGuiApplication from PyQt5.QtWidgets import QFrame, QLabel, QApplication, QWidget, QHBoxLayout, QTableWidget, QAbstractItemView, \ QPushButton, QDialogButtonBox, QVBoxLayout, QTableWidgetItem class DropArea(QLabel): changed = pyqtSignal(QMimeData) def __init__(self, parent=None): super().__init__(parent) self.setMinimumSize(200, 200) self.setFrameStyle(QFrame.Sunken | QFrame.StyledPanel) self.setAlignment(Qt.AlignCenter) self.setAcceptDrops(True) self.setAutoFillBackground(True) self.clear() def clear(self) -> None: self.setText("<drop content>") self.setBackgroundRole(QPalette.Dark) self.changed.emit(None) def dragEnterEvent(self, evt: QtGui.QDragEnterEvent) -> None: self.setText("<drop content>") self.setBackgroundRole(QPalette.Highlight) evt.acceptProposedAction() self.changed.emit(evt.mimeData()) def dragMoveEvent(self, evt: QtGui.QDragMoveEvent) -> None: evt.acceptProposedAction() def dropEvent(self, evt: QtGui.QDropEvent) -> None: mime = evt.mimeData() if mime.hasImage(): print("image") self.setPixmap(mime.imageData()) elif mime.hasHtml(): self.setText(mime.html()) self.setTextFormat(Qt.RichText) elif mime.hasText(): print("text") self.setText(mime.text()) self.setTextFormat(Qt.PlainText) elif mime.hasUrls(): print("url") urls = mime.urls() text = "" for url in urls: text += url.path() + "\n" self.setText(text) else: self.setText("Cannot display data") self.setBackgroundRole(QPalette.Dark) evt.acceptProposedAction() def dragLeaveEvent(self, evt: QtGui.QDragLeaveEvent) -> None: self.clear() evt.accept() class DropSiteWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) abstractLabel = QLabel( "This example accepts drags from other applications and displays the MIME types provided by the drag object.") abstractLabel.setWordWrap(True) abstractLabel.adjustSize() dropArea = DropArea() dropArea.changed.connect(self.updateFormatsTable) self.formatsTable = QTableWidget() formatsTable = self.formatsTable formatsTable.setColumnCount(2) formatsTable.setEditTriggers(QAbstractItemView.NoEditTriggers) formatsTable.setHorizontalHeaderLabels(["Format", "Content"]) formatsTable.horizontalHeader().setStretchLastSection(True) self.clearButton = QPushButton("Clear") self.copyButton = QPushButton("Copy") self.quitButton = QPushButton("Quit") clearButton = self.clearButton copyButton = self.copyButton quitButton = self.quitButton buttonBox = QDialogButtonBox() buttonBox.addButton(clearButton, QDialogButtonBox.ActionRole) buttonBox.addButton(copyButton, QDialogButtonBox.ActionRole) copyButton.setVisible(False) buttonBox.addButton(quitButton, QDialogButtonBox.RejectRole) quitButton.clicked.connect(self.close) clearButton.clicked.connect(dropArea.clear) quitButton.clicked.connect(self.copy) mainLayout = QVBoxLayout(self) mainLayout.addWidget(abstractLabel) mainLayout.addWidget(dropArea) mainLayout.addWidget(formatsTable) mainLayout.addWidget(buttonBox) self.setWindowTitle("Drop Site") self.setMinimumSize(350, 500) def updateFormatsTable(self, mimeData: QMimeData): formatsTable = self.formatsTable formatsTable.setRowCount(0) copyButton = self.copyButton copyButton.setEnabled(False) if not mimeData: return formats = mimeData.formats() for format in formats: formatItem = QTableWidgetItem() formatItem.setFlags(Qt.ItemIsEnabled) formatItem.setTextAlignment(Qt.AlignTop | Qt.AlignLeft) text = "" if format == "text/plain": text = mimeData.text() elif format == "text/html": text = mimeData.html() elif format == "text/uri-list": urls = mimeData.urls() for url in urls: text += url.toString() + " " else: data: QByteArray = mimeData.data(format) for item in data: hex = str(item).strip("b'\\x") text += f' {hex}'.upper() row = formatsTable.rowCount() formatsTable.insertRow(row) formatsTable.setItem(row, 0, QTableWidgetItem(format)) formatsTable.setItem(row, 1, QTableWidgetItem(text)) formatsTable.resizeColumnToContents(0) copyButton.setEnabled(formatsTable.rowCount() > 0) def copy(self): text = "" formatsTable = self.formatsTable for row in range(formatsTable.rowCount()): text += formatsTable.item(row, 0) + ": " + formatsTable.item(row, 1).text() + "\n" QGuiApplication.clipboard().setText(text) if __name__ == '__main__': app = QApplication(sys.argv) window = DropSiteWindow() window.show() app.exec()
PyQt Drag and Drop Puzzle Example
https://doc.qt.io/qt-5/qtwidgets-draganddrop-puzzle-example.html
import sys from PyQt5 import QtGui from PyQt5.QtCore import Qt, QByteArray, QDataStream, QIODevice, QPoint, QMimeData, QObject, QStandardPaths, QDir, \ QSize, QVariant, QRect, pyqtSignal, QCoreApplication, QRandomGenerator from PyQt5.QtGui import QPixmap, QDrag, QPainter, QColor, QImageReader, QIcon, QKeySequence from PyQt5.QtWidgets import QFrame, QLabel, QApplication, QWidget, QHBoxLayout, QMainWindow, QFileDialog, QDialog, \ QMessageBox, QListWidget, QListView, QListWidgetItem, QSizePolicy, QAction, qApp, QMenu class PiecesList(QListWidget): def __init__(self, pieceSize, parent=None): super().__init__(parent) self.setDragEnabled(True) self.setViewMode(QListView.IconMode) self.setIconSize(QSize(pieceSize, pieceSize)) self.setSpacing(10) self.setAcceptDrops(True) self.setDropIndicatorShown(True) @staticmethod def puzzleMimeType(): return "image/x-puzzle-piece" def dragEnterEvent(self, evt: QtGui.QDragEnterEvent) -> None: # print("piecelist drag enter") if evt.mimeData().hasFormat(PiecesList.puzzleMimeType()): evt.accept() else: evt.ignore() def dragMoveEvent(self, evt: QtGui.QDragMoveEvent) -> None: # print("piecelist drag move") if evt.mimeData().hasFormat(PiecesList.puzzleMimeType()): evt.setDropAction(Qt.MoveAction) evt.accept() else: evt.ignore() def dropEvent(self, evt: QtGui.QDropEvent) -> None: # print("piecelist drop event") if evt.mimeData().hasFormat(PiecesList.puzzleMimeType()): pieceData: QByteArray = evt.mimeData().data(PiecesList.puzzleMimeType()) dataStream = QDataStream(pieceData, QIODevice.ReadOnly) pixmap = QPixmap() location = QPoint() dataStream >> pixmap >> location self.addPiece(pixmap, location) evt.setDropAction(Qt.MoveAction) evt.accept() else: evt.ignore() def addPiece(self, pixmap: QPixmap, location: QPoint): pieceItem: QListWidgetItem = QListWidgetItem(self) pieceItem.setIcon(QIcon(pixmap)) pieceItem.setData(Qt.UserRole, QVariant(pixmap)) pieceItem.setData(Qt.UserRole + 1, location) pieceItem.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled) def startDrag(self, supportedActions: Qt.DropActions) -> None: # print("piecelist startDrag") item: QListWidgetItem = self.currentItem() itemData = QByteArray() dataStream = QDataStream(itemData, QIODevice.WriteOnly) pixmap: QPixmap = item.data(Qt.UserRole) location: QPoint = item.data(Qt.UserRole + 1) dataStream << pixmap << location mimeData = QMimeData() mimeData.setData(PiecesList.puzzleMimeType(), itemData) drag = QDrag(self) drag.setMimeData(mimeData) drag.setHotSpot(QPoint(pixmap.width() / 2, pixmap.height() / 2)) drag.setPixmap(pixmap) if drag.exec(Qt.MoveAction) == Qt.MoveAction: ret = self.takeItem(self.row(item)) del ret class Piece: def __init__(self): self.pixmap = QPixmap() self.rect = QRect() self.location = QPoint() class PuzzleWidget(QWidget): puzzleCompleted = pyqtSignal() def __init__(self, imageSize, parent=None): super().__init__(parent) self.m_ImageSize = imageSize self.pieces: [Piece] = [] # 存放 Piece() 对象 self.highlightedRect = QRect() self.inPlace = int() self.setAcceptDrops(True) self.setMinimumSize(imageSize, imageSize) self.setMaximumSize(imageSize, imageSize) def clear(self): self.pieces.clear() self.highlightedRect = QRect() self.inPlace = 0 self.update() def dragEnterEvent(self, evt: QtGui.QDragEnterEvent) -> None: # print("puzzlewidget drag enter") if evt.mimeData().hasFormat(PiecesList.puzzleMimeType()): evt.accept() else: evt.ignore() def dragLeaveEvent(self, evt: QtGui.QDragLeaveEvent) -> None: # print("puzzlewidget drag leave") updateRect = self.highlightedRect self.highlightedRect = QRect() self.update(updateRect) evt.accept() def dragMoveEvent(self, evt: QtGui.QDragMoveEvent) -> None: # print("puzzlewidget drag move") updateRect = self.highlightedRect.united(self.targetSquare(evt.pos())) if evt.mimeData().hasFormat(PiecesList.puzzleMimeType()) and self.findPiece(self.targetSquare(evt.pos())) == -1: self.highlightedRect = self.targetSquare(evt.pos()) evt.setDropAction(Qt.MoveAction) evt.accept() else: self.highlightedRect = QRect() evt.ignore() self.update(updateRect) def dropEvent(self, evt: QtGui.QDropEvent) -> None: # print("puzzlewidget drop event") if evt.mimeData().hasFormat(PiecesList.puzzleMimeType()) and self.findPiece(self.targetSquare(evt.pos()) == -1): pieceData = evt.mimeData().data(PiecesList.puzzleMimeType()) dataStream = QDataStream(pieceData, QIODevice.ReadOnly) piece = Piece() piece.rect = self.targetSquare(evt.pos()) dataStream >> piece.pixmap >> piece.location self.pieces.append(piece) self.update(piece.rect) evt.setDropAction(Qt.MoveAction) evt.accept() if piece.location == piece.rect.topLeft() / self.pieceSize(): self.inPlace += 1 if self.inPlace == 25: self.puzzleCompleted.emit() else: self.highlightedRect = QRect() evt.ignore() def mousePressEvent(self, evt: QtGui.QMouseEvent) -> None: square: QRect = self.targetSquare(evt.pos()) found = self.findPiece(square) if found == -1: return piece: Piece = self.pieces[found] if piece.location == square.topLeft() / self.pieceSize(): self.inPlace -= 1 self.update(square) itemData = QByteArray() dataStream = QDataStream(itemData, QIODevice.WriteOnly) dataStream << piece.pixmap << piece.location mimeData = QMimeData() mimeData.setData(PiecesList.puzzleMimeType(), itemData) drag = QDrag(self) drag.setMimeData(mimeData) drag.setHotSpot(evt.pos() - square.topLeft()) drag.setPixmap(piece.pixmap) if drag.exec(Qt.MoveAction) != Qt.MoveAction: # self.pieces.insert(found, piece) # self.update(self.targetSquare(evt.pos())) if piece.location == square.topLeft() / self.pieceSize(): self.inPlace += 1 else: del self.pieces[found] self.update() def paintEvent(self, evt: QtGui.QPaintEvent) -> None: painter = QPainter(self) painter.fillRect(evt.rect(), Qt.white) if self.highlightedRect.isValid(): painter.setBrush(QColor("#ffcccc")) painter.setPen(Qt.NoPen) painter.drawRect(self.highlightedRect.adjusted(0, 0, -1, -1)) for piece in self.pieces: painter.drawPixmap(piece.rect, piece.pixmap) def findPiece(self, pieceRect: QRect): for i in range(len(self.pieces)): piece: Piece = self.pieces[i] if piece.rect == pieceRect: return i return -1 def targetSquare(self, position: QPoint): k1 = int(position.x() / self.pieceSize()) k2 = int(position.y() / self.pieceSize()) ret = QRect(QPoint(k1*self.pieceSize(),k2*self.pieceSize()), QSize(self.pieceSize(), self.pieceSize())) return ret def pieceSize(self): return self.m_ImageSize / 5 class MainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.setupMenus() self.setupWidgets() self.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) self.setWindowTitle("Puzzle") def setupMenus(self): # print("setupMenus") fileMenu = self.menuBar().addMenu("&File") openAction: QAction = fileMenu.addAction("&Open...", self.openImage) openAction.setShortcuts(QKeySequence.Open) exitAction = fileMenu.addAction("E&xit", QCoreApplication.quit) exitAction.setShortcuts(QKeySequence.Quit) gameMenu: QMenu = self.menuBar().addMenu("&Game") gameMenu.addAction("&Restart", self.setupPuzzle) def setupWidgets(self): frame = QFrame() frameLayout = QHBoxLayout(frame) self.puzzleWidget = PuzzleWidget(800) self.piecesList = PiecesList(self.puzzleWidget.pieceSize(), self) self.puzzleWidget.puzzleCompleted.connect(self.setCompleted, Qt.QueuedConnection) frameLayout.addWidget(self.piecesList) frameLayout.addWidget(self.puzzleWidget) self.setCentralWidget(frame) def openImage(self): try: directory = QStandardPaths.standardLocations(QStandardPaths.PicturesLocation)[0] except Exception as e: directory = QDir.homePath() dialog = QFileDialog(self, "Open Image", directory) dialog.setAcceptMode(QFileDialog.AcceptOpen) dialog.setFileMode(QFileDialog.ExistingFile) mimeTypeFilters = [] for mimeTypeName in QImageReader.supportedMimeTypes(): mimeTypeFilters.append(mimeTypeName.data().decode()) mimeTypeFilters.sort() dialog.setMimeTypeFilters(mimeTypeFilters) dialog.selectMimeTypeFilter("image/jpeg") if dialog.exec() == QDialog.Accepted: self.loadImage(dialog.selectedFiles()[0]) def loadImage(self, fileName): newImage = QPixmap() if not newImage.load(fileName): QMessageBox.warning(self, "Open Image", "The image file could not be loaded.", QMessageBox.Close) return self.puzzleImage = newImage # goto1 self.setupPuzzle() def setCompleted(self): QMessageBox.information(self, "Puzzle Completed", "Congratulations! You have completed the puzzle! Click OK to start again.", QMessageBox.Ok) self.setupPuzzle() def setupPuzzle(self): puzzleImage = self.puzzleImage size = min(puzzleImage.width(), puzzleImage.height()) puzzleImage = puzzleImage.copy((puzzleImage.width() - size) / 2, (puzzleImage.height() - size) / 2, size, size).scaled(self.puzzleWidget.width(), self.puzzleWidget.height(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation) self.piecesList.clear() for x in range(5): for y in range(5): pieceSize = self.puzzleWidget.pieceSize() pieceImage: QPixmap = puzzleImage.copy(x * pieceSize, y * pieceSize, pieceSize, pieceSize) self.piecesList.addPiece(pieceImage, QPoint(x, y)) for i in range(len(self.piecesList)): if QRandomGenerator.global_().bounded(2) == 1: item: QListWidgetItem = self.piecesList.takeItem(i) self.piecesList.insertItem(0, item) self.puzzleWidget.clear() if __name__ == '__main__': app = QApplication(sys.argv) window = MainWindow() window.loadImage("./images/0.jpg") window.show() app.exec()