zoukankan      html  css  js  c++  java
  • 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())
    View Code

    通过继承QWidget,并重写父类方法 printEvent() 来实现,1s 更新一次!!! 

    https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qwidget.html#custom-widgets-and-painting   

    效果图:

    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()
    View Code

    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()
    View Code

    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() + "
    "
                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() + "
    "
    
            QGuiApplication.clipboard().setText(text)
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
    
        window = DropSiteWindow()
        window.show()
    
        app.exec()
    View Code

    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()
    View Code

  • 相关阅读:
    numpy数据集练习——鸢尾花数据集
    git error:gpg failed to sign the data fatal: failed to write commit object
    后台定位Report
    iOS上传构建版本遇到的问题(Xcode8.1)
    动态计算UITableViewCell高度<进阶>
    计算代码运行时间
    安装Homebrew-包管理器
    SDWebImage : NSURLErrorDomain
    nil / Nil / NULL / NSNull
    NSURLCache
  • 原文地址:https://www.cnblogs.com/zach0812/p/13121523.html
Copyright © 2011-2022 走看看