我正在使用pyqt和Python 3.我想在用鼠标拖动时阻止QGraphicsRectItem穿过QGraphicsScene中的水平轴(y = 0)。我使用以下代码(使用height(),因为矩形位于屏幕的上半部分)。请参阅下面的代码的完整示例。
import sys
from PyQt4.QtCore import Qt, QPointF
from PyQt4.QtGui import QGraphicsRectItem, QGraphicsLineItem, QApplication, QGraphicsView, QGraphicsScene, QGraphicsItem
class MyRect(QGraphicsRectItem):
def __init__(self, w, h):
super().__init__(0, 0, w, h)
self.setFlag(QGraphicsItem.ItemIsMovable, True)
self.setFlag(QGraphicsItem.ItemIsSelectable, True)
self.setFlag(QGraphicsItem.ItemIsFocusable, True)
self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
def itemChange(self, change, value):
if change == QGraphicsItem.ItemPositionChange:
if self.y() + self.rect().height() > 0:
return QPointF(self.x(), -self.rect().height())
return value
def main():
# Set up the framework.
app = QApplication(sys.argv)
gr_view = QGraphicsView()
scene = QGraphicsScene()
scene.setSceneRect(-100, -100, 200, 200)
gr_view.setScene(scene)
# Add an x-axis
x_axis = QGraphicsLineItem(-100, 0, 100, 0)
scene.addItem(x_axis)
# Add the restrained rect.
rect = MyRect(50, 50)
rect.setPos(-25, -100) # <--- not clear to me why I have to do this twice to get the
rect.setPos(-25, -100) # item positioned. I know it has to do with my itemChanged above...
scene.addItem(rect)
gr_view.fitInView(0, 0, 200, 200, Qt.KeepAspectRatio)
gr_view.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
原则上这是有效的,但是当我继续将鼠标拖动到水平轴(y = 0)下方时,矩形在拖动时在鼠标位置和其在上部垂线内的约束位置之间来回闪烁和跳跃。因此,看起来拖动首先将其移动到鼠标光标,然后只能追溯调整位置。我想在项目移动(明显)之前进行调整。
答案 0 :(得分:2)
您使用self.y() + self.rect().height() > 0
来测试项目是否仍在y轴上方。但是,self.y()
指的是旧/当前位置。您应该使用value.y()
测试新位置。
所以方法应该是:
def itemChange(self, change, value):
if change == QGraphicsItem.ItemPositionChange:
if value.y() + self.rect().height() > 0:
return QPointF(value.x(), -self.rect().height())
return super().itemChange(change, value) # Call super
请注意,如果测试通过,则返回value.x()
,如果测试失败,则调用超类的itemChange
(就像itemChange Qt documentation中的C ++示例一样)