Christopher M. Nahler
Thu, 26 Aug 2010 00:46:02 -0700
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