Thank you Baz! You pointed me to the solution of my problem ... and it
was easier than your solution :-)
I did not know of *self.viewport()* in the view class.
Updating the cursor of the view with self.viewport().setCursor() instead
of just self.setCursor() did the trick.
On 25.08.2010 20:05, Baz Walter wrote:
On 25/08/10 09:54, Christopher M. Nahler wrote:
I'll take it as an "if all else fails" solution :-) not giving hope
up now!
I have changed the item cursors and view cursors to be differnt to see
which one wins as sometimes it looked as if it was working. But it turns
out its the item cursors that wins.
After reading more on cursors I have found that application override
cursor works with a stack. Is this also the case with the "normal" item
cursors? Do I need to unset cursors? I see a reference to a
unsetCursor() function but cannot find details to it.
attempting to get this to work by setting the cursor on the view
and/or the items can be quite, um, "challenging". it reminds me of one
of those puzzles where you have to roll several ball bearings around
at once trying to get them all to land in little holes :)
the main problem seems to be that setting the cursor on any item may
reset the cursor on the view, depending on whether the mouse is
currently over an item or not (amongst other things).
one way to solve this would be to avoid setting the cursor on the
items altogether, and to use mouse/keyboard events on the view to
dynamically control the current cursor shape.
here's an implementation that hopefully does what you want:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class MyRect(QGraphicsRectItem):
def __init__(self, parent=None, scene=None):
# init parent
super().__init__(parent, scene)
# set flags
self.setFlag(QGraphicsItem.ItemIsSelectable, True)
self.setFlag(QGraphicsItem.ItemIsMovable, True)
self.setFlag(self.ItemSendsGeometryChanges, True)
self.setAcceptHoverEvents(True)
def paint(self, painter, option, widget):
if self.isSelected():
painter.setPen(QPen(Qt.black, 1, Qt.DotLine))
else:
painter.setPen(QPen(Qt.black, 1, Qt.SolidLine))
painter.setBrush(QBrush(Qt.white, Qt.SolidPattern))
painter.drawRect(self.rect())
class MyView(QGraphicsView):
def __init__(self, parent=None):
super().__init__(parent)
self.setMouseTracking(True)
self.scale(1,1)
self.startPos = None
def setSelectMode(self):
print("view setting select mode")
self.scene().setViewMode(MyScene.SELECTMODE)
def setEditMode(self):
print("view setting edit mode")
self.scene().setViewMode(MyScene.EDITMODE)
if len(self.scene().selectedItems()) > 1:
self.scene().clearSelection()
def setDrawMode(self):
print("view setting draw mode")
self.scene().setViewMode(MyScene.DRAWMODE)
self.scene().clearSelection()
def drawBackground(self, painter, rect):
# draw a rect in size of sceneRect
painter.setPen(QPen(Qt.red, 0, Qt.NoPen))
painter.setBrush(QBrush(Qt.lightGray, Qt.SolidPattern))
painter.drawRect(self.scene().sceneRect())
def mousePressEvent(self, mouseEvent):
print("view mousePress")
curPos = mouseEvent.pos()
self.startPos = self.mapToScene(curPos)
if self.scene().viewMode() == MyScene.DRAWMODE:
self.scene().newItem = MyRect(scene=self.scene())
self.scene().newItem.setRect(QRectF(self.startPos,
QSizeF(0, 0)))
self.scene().newItem.setSelected(True)
else:
super().mousePressEvent(mouseEvent)
### generic method for setting the cursor
def updateCursor(self):
m = self.scene().viewMode()
if m == MyScene.SELECTMODE:
item = self.itemAt(self.mapFromGlobal(QCursor.pos()))
if item is None:
self.viewport().setCursor(Qt.ArrowCursor)
else:
self.viewport().setCursor(Qt.OpenHandCursor)
elif m == MyScene.EDITMODE:
self.viewport().setCursor(Qt.ForbiddenCursor)
elif m == MyScene.DRAWMODE:
self.viewport().setCursor(Qt.CrossCursor)
def mouseMoveEvent(self, mouseEvent):
### dynamically set the cursor
self.updateCursor()
if self.scene().viewMode() == MyScene.DRAWMODE:
if self.scene().newItem:
curPos = self.mapToScene(mouseEvent.pos())
newRectF = QRectF(self.startPos, curPos)
if newRectF != self.scene().newItem.rect():
self.scene().newItem.setRect(newRectF.normalized())
else:
super().mouseMoveEvent(mouseEvent)
def mouseReleaseEvent(self, mouseEvent):
print("view mouseRelease")
if self.scene().newItem:
# delete item if zero height or width
if (self.scene().newItem.rect().width() == 0
or self.scene().newItem.rect().height() == 0):
self.scene().removeItem(self.scene().newItem)
del self.scene().newItem
self.startPos = None
self.scene().newItem = None
super().mouseReleaseEvent(mouseEvent)
### the default behaviour may unset the cursor, so reset it here
self.updateCursor()
def keyPressEvent(self, keyEvent):
if keyEvent.key() == Qt.Key_F1:
self.setSelectMode()
self.updateCursor()
elif keyEvent.key() == Qt.Key_F2:
self.setEditMode()
self.updateCursor()
elif keyEvent.key() == Qt.Key_F3:
self.setDrawMode()
self.updateCursor()
elif keyEvent.key() == Qt.Key_Delete:
if self.scene().viewMode() == MyScene.SELECTMODE:
items = self.scene().selectedItems()
if len(items):
for item in items:
self.scene().removeItem(item)
del item
class MyScene(QGraphicsScene):
SELECTMODE, EDITMODE, DRAWMODE = (0, 1, 2)
validViewModes = [SELECTMODE, EDITMODE, DRAWMODE]
def __init__(self, parent=None):
super().__init__(parent)
self._viewMode = MyScene.SELECTMODE
self.newItem = None
self.setSceneRect(-300, -200, 600, 400)
# add some item
someRect = MyRect(scene=self)
someRect.setRect(QRectF(0, 0, 160, 80))
# add another item
anotherRect = MyRect(scene=self)
anotherRect.setRect(QRectF(-80, -40, 80, 160))
def setViewMode(self, value):
if value != self._viewMode:
if value in MyScene.validViewModes:
self._viewMode = value
else:
raise ValueError("invalid view mode")
def viewMode(self):
return self._viewMode
class MainWindow(QMainWindow):
def __init__(self, parent=None):
# call parent init
super().__init__(parent)
# setup scene object
self.scene = MyScene()
# setup view object
self.view = MyView()
# connect scene to view
self.view.setScene(self.scene)
# create layout
layout = QVBoxLayout()
# add view to layout
layout.addWidget(self.view)
# set the margin of the object in the layout
layout.setContentsMargins(0, 0, 0, 0)
# create the central widget
self.widget = QWidget()
# lay it out
self.widget.setLayout(layout)
# set it to central
self.setCentralWidget(self.widget)
if __name__ == "__main__":
import sys
# setup application object
app = QApplication(sys.argv)
# create (parent) main window
mainWindow = MainWindow()
mainWindow.setWindowTitle("testScene")
mainWindow.show()
# run application object
sys.exit(app.exec_())
_______________________________________________
PyQt mailing list PyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt