lightning2911
5th May 2010, 10:40
I am stuck with two versions of code that only differ in the way the rect is assigned. How are they different? and how does this effect the different behaviour?
(What I want is rectangles that are painted correctly with another style for selected ones and that can be moved around if in selection mode. I distinguish the mode in self.newItem. If True I am in adding-rectangles mode and if False I am in selection mode.)
This code below produces rectangles that are
- painted "correct" (snapped to grid)
- are selectable (but not drawn in red and yellow as in the paint method but with a black dashed line; although in debugging i see that the if-code for selected is visited)
- can be moved (snapped to grid)
class DesignerBlock(QGraphicsRectItem):
def __init__(self, rect=QRectF(0, 0, 0, 0), parent=None, scene=None):
super(DesignerBlock, self).__init__(parent, scene)
self.setFlag(self.ItemIsMovable, True)
self.setFlag(self.ItemIsSelectable, True)
self.setFlag(self.ItemSendsGeometryChanges, True)
self.setPen(QPen(Qt.black, 1, Qt.SolidLine))
self.setBrush(QBrush(Qt.white, Qt.SolidPattern))
self.moving = False
self.setRect(rect) # <-----
self.setSelected(True)
self.setFocus()
self.update()
def paint(self, painter, option, widget):
pen = self.pen()
brush = self.brush()
if self.isSelected():
pen = QPen(Qt.red, 1, Qt.SolidLine)
brush = QBrush(Qt.yellow, Qt.SolidPattern)
painter.setPen(pen)
painter.setBrush(brush)
painter.drawRect(self.rect()) # <-----
super(DesignerBlock, self).paint(painter, option, widget)
def deferPosition(self, value):
big = abs(value) / SCREEN_GRID
little = abs(value) % SCREEN_GRID
if little > (SCREEN_GRID / 2):
little = 1
else:
little = 0
if value > 0:
direction = 1
else:
direction = -1
return (big + little) * SCREEN_GRID * direction
def itemChange(self, change, value):
if change == QGraphicsItem.ItemPositionChange:
x = value.toPoint().x()
y = value.toPoint().y()
newPosition = value.toPoint()
newPosition.setX(self.deferPosition(x))
newPosition.setY(self.deferPosition(y))
return newPosition
else:
return value
Now this code below (the same except the two indicated changes) makes rectangles that
- are painted only in the rect of the mouse selection (but not adjusted to snap to grid)
with that i mean that if i rubberband a rect smaller than the grid point, only this area is painted although after i force a repaint (as in window minimize/maximize) the rectitem is drawn correct from gridPoint to gridPoint.
- selected rect is painted in red and yellow
- when selecting with rubberband the view is "erased" and click select does not work and they dont move
class DesignerBlock(QGraphicsRectItem):
def __init__(self, rect=QRectF(0, 0, 0, 0), parent=None, scene=None):
super(DesignerBlock, self).__init__(parent, scene)
self.setFlag(self.ItemIsMovable, True)
self.setFlag(self.ItemIsSelectable, True)
self.setFlag(self.ItemSendsGeometryChanges, True)
self.setPen(QPen(Qt.black, 1, Qt.SolidLine))
self.setBrush(QBrush(Qt.white, Qt.SolidPattern))
self.moving = False
self.rect = rect # <----------
#self.setRect(rect)
self.setSelected(True)
self.setFocus()
self.update()
def paint(self, painter, option, widget):
pen = self.pen()
brush = self.brush()
if self.isSelected():
pen = QPen(Qt.red, 1, Qt.SolidLine)
brush = QBrush(Qt.yellow, Qt.SolidPattern)
painter.setPen(pen)
painter.setBrush(brush)
painter.drawRect(self.rect) # <-----------
#painter.drawRect(self.rect())
super(DesignerBlock, self).paint(painter, option, widget)
def deferPosition(self, value):
big = abs(value) / SCREEN_GRID
little = abs(value) % SCREEN_GRID
if little > (SCREEN_GRID / 2):
little = 1
else:
little = 0
if value > 0:
direction = 1
else:
direction = -1
return (big + little) * SCREEN_GRID * direction
def itemChange(self, change, value):
if change == QGraphicsItem.ItemPositionChange:
x = value.toPoint().x()
y = value.toPoint().y()
newPosition = value.toPoint()
newPosition.setX(self.deferPosition(x))
newPosition.setY(self.deferPosition(y))
return newPosition
else:
return value
this is scene code for handling the mouse events:
def mousePressEvent(self, mouseEvent):
self.startPos = mouseEvent.scenePos()
self.emit(SIGNAL("startSet"), self.gridPos(self.startPos))
if self.newItem == False:
super(DesignerScene, self).mousePressEvent(mouseEvent)
def mouseMoveEvent(self, mouseEvent):
self.emit(SIGNAL("updateCoords"), self.gridPos(mouseEvent.scenePos()))
super(DesignerScene, self).mouseMoveEvent(mouseEvent)
def mouseReleaseEvent(self, mouseEvent):
self.endPos = mouseEvent.scenePos()
self.emit(SIGNAL("endSet"), self.gridPos(self.endPos))
if self.newItem:
self.emit(SIGNAL("createBox"), self.gridPos(self.startPos), self.gridPos(self.endPos))
else:
super(DesignerScene, self).mousePressEvent(mouseEvent)
def createBox(self, start, end):
xs = start.x()
ys = start.y()
xe = end.x()
ye = end.y()
if ys <> ye and xs <> xe:
# insert only if not a line
self.addItem(DesignerBlock(QRectF(xs, ys, xe-xs, ye-ys).normalized()))
(What I want is rectangles that are painted correctly with another style for selected ones and that can be moved around if in selection mode. I distinguish the mode in self.newItem. If True I am in adding-rectangles mode and if False I am in selection mode.)
This code below produces rectangles that are
- painted "correct" (snapped to grid)
- are selectable (but not drawn in red and yellow as in the paint method but with a black dashed line; although in debugging i see that the if-code for selected is visited)
- can be moved (snapped to grid)
class DesignerBlock(QGraphicsRectItem):
def __init__(self, rect=QRectF(0, 0, 0, 0), parent=None, scene=None):
super(DesignerBlock, self).__init__(parent, scene)
self.setFlag(self.ItemIsMovable, True)
self.setFlag(self.ItemIsSelectable, True)
self.setFlag(self.ItemSendsGeometryChanges, True)
self.setPen(QPen(Qt.black, 1, Qt.SolidLine))
self.setBrush(QBrush(Qt.white, Qt.SolidPattern))
self.moving = False
self.setRect(rect) # <-----
self.setSelected(True)
self.setFocus()
self.update()
def paint(self, painter, option, widget):
pen = self.pen()
brush = self.brush()
if self.isSelected():
pen = QPen(Qt.red, 1, Qt.SolidLine)
brush = QBrush(Qt.yellow, Qt.SolidPattern)
painter.setPen(pen)
painter.setBrush(brush)
painter.drawRect(self.rect()) # <-----
super(DesignerBlock, self).paint(painter, option, widget)
def deferPosition(self, value):
big = abs(value) / SCREEN_GRID
little = abs(value) % SCREEN_GRID
if little > (SCREEN_GRID / 2):
little = 1
else:
little = 0
if value > 0:
direction = 1
else:
direction = -1
return (big + little) * SCREEN_GRID * direction
def itemChange(self, change, value):
if change == QGraphicsItem.ItemPositionChange:
x = value.toPoint().x()
y = value.toPoint().y()
newPosition = value.toPoint()
newPosition.setX(self.deferPosition(x))
newPosition.setY(self.deferPosition(y))
return newPosition
else:
return value
Now this code below (the same except the two indicated changes) makes rectangles that
- are painted only in the rect of the mouse selection (but not adjusted to snap to grid)
with that i mean that if i rubberband a rect smaller than the grid point, only this area is painted although after i force a repaint (as in window minimize/maximize) the rectitem is drawn correct from gridPoint to gridPoint.
- selected rect is painted in red and yellow
- when selecting with rubberband the view is "erased" and click select does not work and they dont move
class DesignerBlock(QGraphicsRectItem):
def __init__(self, rect=QRectF(0, 0, 0, 0), parent=None, scene=None):
super(DesignerBlock, self).__init__(parent, scene)
self.setFlag(self.ItemIsMovable, True)
self.setFlag(self.ItemIsSelectable, True)
self.setFlag(self.ItemSendsGeometryChanges, True)
self.setPen(QPen(Qt.black, 1, Qt.SolidLine))
self.setBrush(QBrush(Qt.white, Qt.SolidPattern))
self.moving = False
self.rect = rect # <----------
#self.setRect(rect)
self.setSelected(True)
self.setFocus()
self.update()
def paint(self, painter, option, widget):
pen = self.pen()
brush = self.brush()
if self.isSelected():
pen = QPen(Qt.red, 1, Qt.SolidLine)
brush = QBrush(Qt.yellow, Qt.SolidPattern)
painter.setPen(pen)
painter.setBrush(brush)
painter.drawRect(self.rect) # <-----------
#painter.drawRect(self.rect())
super(DesignerBlock, self).paint(painter, option, widget)
def deferPosition(self, value):
big = abs(value) / SCREEN_GRID
little = abs(value) % SCREEN_GRID
if little > (SCREEN_GRID / 2):
little = 1
else:
little = 0
if value > 0:
direction = 1
else:
direction = -1
return (big + little) * SCREEN_GRID * direction
def itemChange(self, change, value):
if change == QGraphicsItem.ItemPositionChange:
x = value.toPoint().x()
y = value.toPoint().y()
newPosition = value.toPoint()
newPosition.setX(self.deferPosition(x))
newPosition.setY(self.deferPosition(y))
return newPosition
else:
return value
this is scene code for handling the mouse events:
def mousePressEvent(self, mouseEvent):
self.startPos = mouseEvent.scenePos()
self.emit(SIGNAL("startSet"), self.gridPos(self.startPos))
if self.newItem == False:
super(DesignerScene, self).mousePressEvent(mouseEvent)
def mouseMoveEvent(self, mouseEvent):
self.emit(SIGNAL("updateCoords"), self.gridPos(mouseEvent.scenePos()))
super(DesignerScene, self).mouseMoveEvent(mouseEvent)
def mouseReleaseEvent(self, mouseEvent):
self.endPos = mouseEvent.scenePos()
self.emit(SIGNAL("endSet"), self.gridPos(self.endPos))
if self.newItem:
self.emit(SIGNAL("createBox"), self.gridPos(self.startPos), self.gridPos(self.endPos))
else:
super(DesignerScene, self).mousePressEvent(mouseEvent)
def createBox(self, start, end):
xs = start.x()
ys = start.y()
xe = end.x()
ye = end.y()
if ys <> ye and xs <> xe:
# insert only if not a line
self.addItem(DesignerBlock(QRectF(xs, ys, xe-xs, ye-ys).normalized()))