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)

Qt Code:
  1. class DesignerBlock(QGraphicsRectItem):
  2. def __init__(self, rect=QRectF(0, 0, 0, 0), parent=None, scene=None):
  3. super(DesignerBlock, self).__init__(parent, scene)
  4. self.setFlag(self.ItemIsMovable, True)
  5. self.setFlag(self.ItemIsSelectable, True)
  6. self.setFlag(self.ItemSendsGeometryChanges, True)
  7. self.setPen(QPen(Qt.black, 1, Qt.SolidLine))
  8. self.setBrush(QBrush(Qt.white, Qt.SolidPattern))
  9. self.moving = False
  10. self.setRect(rect) # <-----
  11. self.setSelected(True)
  12. self.setFocus()
  13. self.update()
  14.  
  15. def paint(self, painter, option, widget):
  16. pen = self.pen()
  17. brush = self.brush()
  18. if self.isSelected():
  19. pen = QPen(Qt.red, 1, Qt.SolidLine)
  20. brush = QBrush(Qt.yellow, Qt.SolidPattern)
  21. painter.setPen(pen)
  22. painter.setBrush(brush)
  23. painter.drawRect(self.rect()) # <-----
  24. super(DesignerBlock, self).paint(painter, option, widget)
  25.  
  26. def deferPosition(self, value):
  27. big = abs(value) / SCREEN_GRID
  28. little = abs(value) % SCREEN_GRID
  29.  
  30. if little > (SCREEN_GRID / 2):
  31. little = 1
  32. else:
  33. little = 0
  34.  
  35. if value > 0:
  36. direction = 1
  37. else:
  38. direction = -1
  39.  
  40. return (big + little) * SCREEN_GRID * direction
  41.  
  42.  
  43. def itemChange(self, change, value):
  44. if change == QGraphicsItem.ItemPositionChange:
  45. x = value.toPoint().x()
  46. y = value.toPoint().y()
  47. newPosition = value.toPoint()
  48.  
  49. newPosition.setX(self.deferPosition(x))
  50.  
  51. newPosition.setY(self.deferPosition(y))
  52.  
  53. return newPosition
  54. else:
  55. return value
To copy to clipboard, switch view to plain text mode 

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

Qt Code:
  1. class DesignerBlock(QGraphicsRectItem):
  2. def __init__(self, rect=QRectF(0, 0, 0, 0), parent=None, scene=None):
  3. super(DesignerBlock, self).__init__(parent, scene)
  4. self.setFlag(self.ItemIsMovable, True)
  5. self.setFlag(self.ItemIsSelectable, True)
  6. self.setFlag(self.ItemSendsGeometryChanges, True)
  7. self.setPen(QPen(Qt.black, 1, Qt.SolidLine))
  8. self.setBrush(QBrush(Qt.white, Qt.SolidPattern))
  9. self.moving = False
  10. self.rect = rect # <----------
  11. #self.setRect(rect)
  12. self.setSelected(True)
  13. self.setFocus()
  14. self.update()
  15.  
  16. def paint(self, painter, option, widget):
  17. pen = self.pen()
  18. brush = self.brush()
  19. if self.isSelected():
  20. pen = QPen(Qt.red, 1, Qt.SolidLine)
  21. brush = QBrush(Qt.yellow, Qt.SolidPattern)
  22. painter.setPen(pen)
  23. painter.setBrush(brush)
  24. painter.drawRect(self.rect) # <-----------
  25. #painter.drawRect(self.rect())
  26. super(DesignerBlock, self).paint(painter, option, widget)
  27.  
  28. def deferPosition(self, value):
  29. big = abs(value) / SCREEN_GRID
  30. little = abs(value) % SCREEN_GRID
  31.  
  32. if little > (SCREEN_GRID / 2):
  33. little = 1
  34. else:
  35. little = 0
  36.  
  37. if value > 0:
  38. direction = 1
  39. else:
  40. direction = -1
  41.  
  42. return (big + little) * SCREEN_GRID * direction
  43.  
  44.  
  45. def itemChange(self, change, value):
  46. if change == QGraphicsItem.ItemPositionChange:
  47. x = value.toPoint().x()
  48. y = value.toPoint().y()
  49. newPosition = value.toPoint()
  50.  
  51. newPosition.setX(self.deferPosition(x))
  52.  
  53. newPosition.setY(self.deferPosition(y))
  54.  
  55. return newPosition
  56. else:
  57. return value
To copy to clipboard, switch view to plain text mode 

this is scene code for handling the mouse events:
Qt Code:
  1. def mousePressEvent(self, mouseEvent):
  2. self.startPos = mouseEvent.scenePos()
  3. self.emit(SIGNAL("startSet"), self.gridPos(self.startPos))
  4. if self.newItem == False:
  5. super(DesignerScene, self).mousePressEvent(mouseEvent)
  6.  
  7. def mouseMoveEvent(self, mouseEvent):
  8. self.emit(SIGNAL("updateCoords"), self.gridPos(mouseEvent.scenePos()))
  9. super(DesignerScene, self).mouseMoveEvent(mouseEvent)
  10.  
  11. def mouseReleaseEvent(self, mouseEvent):
  12. self.endPos = mouseEvent.scenePos()
  13. self.emit(SIGNAL("endSet"), self.gridPos(self.endPos))
  14. if self.newItem:
  15. self.emit(SIGNAL("createBox"), self.gridPos(self.startPos), self.gridPos(self.endPos))
  16. else:
  17. super(DesignerScene, self).mousePressEvent(mouseEvent)
  18.  
  19. def createBox(self, start, end):
  20. xs = start.x()
  21. ys = start.y()
  22. xe = end.x()
  23. ye = end.y()
  24. if ys <> ye and xs <> xe:
  25. # insert only if not a line
  26. self.addItem(DesignerBlock(QRectF(xs, ys, xe-xs, ye-ys).normalized()))
To copy to clipboard, switch view to plain text mode