【问题标题】:How do I reimplement the itemChange and mouseMoveEvent of a QGraphicsPixmapItem?如何重新实现 QGraphicsPixmapItem 的 itemChange 和 mouseMoveEvent?
【发布时间】:2019-09-10 06:30:18
【问题描述】:

我正在使用 PySide 构建一个 T 恤设计器。为此,我设置了一个 QGraphicsScene,其中 T 恤的图像作为场景中的 QPixmapItem。为了在 T 恤上叠加设计,我从用户那里获取了设计图像 PNG,并将其设置为另一个 QPixmapItem。我使用 setPos() 方法将它们对齐,然后使用 setZValue() 方法确保 Design PNG 显示在 T 恤图像的顶部。

我为设计图像 QPixmapItem 启用了标志 ItemIsMovable、ItemIsSelectable、ItemSendsScenePositionChanges、ItemIsFocusable。所以我可以在 T 恤图像上移动设计。接下来,我想将此运动限制在可以打印的地方。为了实现这一点,我按照this question 派生了一个新的 QGraphicsPixmapItem 类,并尝试重新实现 itemChange() 和 mouseMoveEvent() 方法。

在这些方法中,我尝试使用 super() 以及常规方式 QGraphicsPixmapItem.itemChange(change, event) 调用原始 QPixmapItem 类的相同方法。然而,似乎什么都没有发生。设计移动得很好,但没有受到限制。为了查看该方法是否被调用,我在这些方法中添加了打印语句,但它们没有被执行。

我也尝试在场景中添加 setSceneRect()。我还在 QGraphicsView 上启用了 setMouseTracking。但是,这些事情都不会触发 itemChanged() 或 mouseMoveEvent()。

还有其他问题,人们已经解释了如何在 C++ 中执行此操作。但是,我无法在 python 中复制它。

# -*- coding: utf-8 -*-

from PySide import QtCore, QtGui
from os import path

class Pixmap(QtGui.QGraphicsPixmapItem):

    def __init__(self, pix):
        super(Pixmap, self).__init__()
        self.pixmap_item = QtGui.QGraphicsPixmapItem(pix)
        self.pixmap_item.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
        self.pixmap_item.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
        self.pixmap_item.setFlag(QtGui.QGraphicsItem.ItemSendsScenePositionChanges, True)
        self.pixmap_item.setFlag(QtGui.QGraphicsItem.ItemIsFocusable, True)

    def itemChange(self, change, event):
        QtGui.QGraphicsPixmapItem.itemChange(change, event)
        print "Item Changed"
        #Code to restrict to a rectangular area goes here
        return QtGui.QGraphicsPixmapItem.itemChange(self, change, event)

    def mouseMoveEvent(self, event):
        super(Pixmap, self).mouseMoveEvent(event)
        print "Mouse Moved"
        #Code to restrict to a rectangular area goes here

class Ui_frmSelectRoundNeckHalfSleeve(QtCore.QObject):

    def setupUi(self, frmSelectRoundNeckHalfSleeve):
        frmSelectRoundNeckHalfSleeve.setObjectName("frmSelectRoundNeckHalfSleeve")
        frmSelectRoundNeckHalfSleeve.resize(842, 595)
        self.imgRoundNeckTShirt = QtGui.QGraphicsView(frmSelectRoundNeckHalfSleeve)
        self.imgRoundNeckTShirt.setGeometry(QtCore.QRect(20, 20, 500, 500))
        self.imgRoundNeckTShirt.setObjectName("imgRoundNeckTShirt")
        self.imgRoundNeckTShirt.setMouseTracking(True)

        self.tShirtScene = QtGui.QGraphicsScene(frmSelectRoundNeckHalfSleeve)
        self.tShirtScene.setSceneRect(20, 20, 480, 480)
        self.TShirtImage = QtGui.QGraphicsPixmapItem(QtGui.QPixmap("./Images/black-t-shirt.jpg").scaled(480, 480, QtCore.Qt.KeepAspectRatio))
        self.designImagePixmap = QtGui.QPixmap("./Designs/test.png")
        self.designImagePng = Pixmap(self.designImagePixmap.scaledToWidth(135,QtCore.Qt.SmoothTransformation))
        self.TShirtImage.setZValue(10)
        self.designImagePng.pixmap_item.setZValue(40)
        self.designImagePng.pixmap_item.setPos(167,90)
        self.tShirtScene.addItem(self.TShirtImage)
        self.tShirtScene.addItem(self.designImagePng.pixmap_item)
        self.imgRoundNeckTShirt.setScene(self.tShirtScene)

if __name__ == "__main__":

    path = r"E:\\Documents\\T Shirt Designer\\"
    QtGui.QApplication.addLibraryPath(path)

    app = QtGui.QApplication(sys.argv)
    testFile = QtGui.QWidget()
    ui = Ui_frmSelectRoundNeckHalfSleeve()
    ui.setupUi(testFile)

    testFile.show()
    sys.exit(app.exec_())

【问题讨论】:

    标签: python python-2.7 pyside qgraphicsitem qgraphicspixmapitem


    【解决方案1】:

    您遇到的错误是您没有覆盖 pixmap_item itemChange 而是一个 Pixmap。您似乎将继承与组合混淆了。

    一个改进是基础项目(T恤)是设计项目的父亲,因此设计项目的坐标是相对于基础项目的。

    考虑到前面的事情,我已经实现了将设计项目的移动限制在 T 恤项目空间的逻辑。

    # -*- coding: utf-8 -*-
    
    import sys
    from os import path
    from PySide import QtCore, QtGui
    
    
    class Pixmap(QtGui.QGraphicsPixmapItem):
        def __init__(self, pix, parent=None):
            super(Pixmap, self).__init__(pix, parent)
            self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
            self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
            self.setFlag(QtGui.QGraphicsItem.ItemSendsScenePositionChanges, True)
            self.setFlag(QtGui.QGraphicsItem.ItemIsFocusable, True)
    
        def itemChange(self, change, value):
            if change == QtGui.QGraphicsItem.ItemPositionChange:
                parent = self.parentItem()
                if parent is not None:
                    r = self.mapToParent(self.boundingRect()).boundingRect()
                    R = parent.boundingRect()
                    rR = QtCore.QRectF(R.topLeft(), R.size() - r.size())
                    if not rR.contains(value):
                        x = min(max(rR.left(), value.x()), rR.right())
                        y = min(max(rR.top(), value.y()), rR.bottom())
                        return QtCore.QPointF(x, y)
            return QtGui.QGraphicsPixmapItem.itemChange(self, change, value)
    
    
    class Ui_frmSelectRoundNeckHalfSleeve(QtCore.QObject):
        def setupUi(self, frmSelectRoundNeckHalfSleeve):
            frmSelectRoundNeckHalfSleeve.setObjectName(
                "frmSelectRoundNeckHalfSleeve"
            )
            frmSelectRoundNeckHalfSleeve.resize(842, 595)
            self.imgRoundNeckTShirt = QtGui.QGraphicsView(
                frmSelectRoundNeckHalfSleeve
            )
            self.imgRoundNeckTShirt.setGeometry(QtCore.QRect(20, 20, 500, 500))
            self.imgRoundNeckTShirt.setObjectName("imgRoundNeckTShirt")
    
            self.tShirtScene = QtGui.QGraphicsScene(frmSelectRoundNeckHalfSleeve)
            self.tShirtScene.setSceneRect(20, 20, 480, 480)
            self.TShirtImage = QtGui.QGraphicsPixmapItem(
                QtGui.QPixmap("./Images/black-t-shirt.jpg").scaled(
                    480, 480, QtCore.Qt.KeepAspectRatio
                )
            )
            designImagePixmap = QtGui.QPixmap("./Designs/test.png").scaledToWidth(
                135, QtCore.Qt.SmoothTransformation
            )
            self.designImagePng = Pixmap(designImagePixmap, self.TShirtImage)
            self.designImagePng.setZValue(1)
            self.designImagePng.setPos(167, 90)
            self.tShirtScene.addItem(self.TShirtImage)
            self.imgRoundNeckTShirt.setScene(self.tShirtScene)
    
    
    if __name__ == "__main__":
    
        path = r"E:\\Documents\\T Shirt Designer\\"
        QtGui.QApplication.addLibraryPath(path)
        app = QtGui.QApplication(sys.argv)
        testFile = QtGui.QWidget()
        ui = Ui_frmSelectRoundNeckHalfSleeve()
        ui.setupUi(testFile)
        testFile.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 非常感谢。这解决了这个问题。我使用您的育儿理念将设计限制在 T 恤图像内的矩形可打印区域。完全按照我的意愿工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-10
    • 1970-01-01
    • 2020-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多