python - How do I reimplement the itemChange and mouseMoveEvent of a QGraphicsPixmapItem?
问题描述
I'm building a T Shirt Designer using PySide. For this, I've set up a QGraphicsScene with the image of the T Shirt as a QPixmapItem on the scene. To overlay the design on the T Shirt, I'm getting the design image PNG from the user and setting that up as another QPixmapItem. I align them up using the setPos() method and then use the setZValue() method to ensure that the Design PNG shows up on top of the T Shirt image.
I've enabled the flags ItemIsMovable, ItemIsSelectable, ItemSendsScenePositionChanges, ItemIsFocusable for the Design image QPixmapItem. So I am able to move the design around over the T Shirt image. Next, I want to restrict this movement to only where the printing is possible. To achieve this, I've followed this question to derive a new QGraphicsPixmapItem class and have tried to reimplement both the itemChange() and the mouseMoveEvent() methods.
Inside these methods, I've tried calling the same methods of the original QPixmapItem class using both super() as well as the regular way QGraphicsPixmapItem.itemChange(change, event). However, nothing seems to be happening. The design moves just fine but it's not getting restricted. To see if the method gets called I added print statements inside these methods but they don't get executed.
I've tried adding setSceneRect() in the scene as well. I've also enabled setMouseTracking on the QGraphicsView. However, none of those things triggers either the itemChanged() or mouseMoveEvent().
There are other questions where people have explained how to do this in C++. However, I'm not able to replicate it in 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_())
解决方案
The error you have is that you are not overwriting the pixmap_item itemChange but a Pixmap. It seems you are confusing inheritance with composition.
An improvement is that the base item (T-shirt) is the father of the design item so that the coordinates of the design item are relative to the base item.
Considering the previous thing I have implemented the logic to restrict the movement of the design item to the space of the T-shirt Item.
# -*- 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_())
推荐阅读
- c++ - 为所有对象创建相同的属性
- ruby-on-rails - 如何强制 cron 作业在 Rails 中的 PST 时间运行?
- javascript - 如何更改 React Native 中的警报按钮颜色?
- python - 如何在 Pandas DataFrame 的特定列中达到最小值后删除行?
- eclipse - WAR 部署不包含类
- xamarin.forms - 如何在不活动超时后以编程方式唤醒 Zebra 蓝牙打印机?
- scheme - 如何更改 Atom 中的 Script 包以使用 Scheme 而不是 Guile 运行代码?
- c# - 跨多个项目参考解决方案文件夹中的 txt 文件以进行家庭作业
- spring - 我们是否直接在 DEV、QA 或 PROD 等环境中使用 GitHub 中的 Spring Web 应用程序代码?
- twitter - 消息中的 Twitter 蓝色背景