bugfixes
This commit is contained in:
parent
d4e8e2b883
commit
aaece4badc
@ -298,6 +298,7 @@ class Canvas(QtGui.QWidget):
|
|||||||
Common options are name, pos, scale, and z
|
Common options are name, pos, scale, and z
|
||||||
"""
|
"""
|
||||||
citem = CanvasItem(item, **opts)
|
citem = CanvasItem(item, **opts)
|
||||||
|
item._canvasItem = citem
|
||||||
self.addItem(citem)
|
self.addItem(citem)
|
||||||
return citem
|
return citem
|
||||||
|
|
||||||
@ -493,12 +494,13 @@ class Canvas(QtGui.QWidget):
|
|||||||
def removeItem(self, item):
|
def removeItem(self, item):
|
||||||
if isinstance(item, CanvasItem):
|
if isinstance(item, CanvasItem):
|
||||||
item.setCanvas(None)
|
item.setCanvas(None)
|
||||||
#self.view.scene().removeItem(item.item)
|
|
||||||
self.itemList.removeTopLevelItem(item.listItem)
|
self.itemList.removeTopLevelItem(item.listItem)
|
||||||
#del self.items[item.name]
|
|
||||||
self.items.remove(item)
|
self.items.remove(item)
|
||||||
else:
|
else:
|
||||||
self.view.removeItem(item)
|
if hasattr(item, '_canvasItem'):
|
||||||
|
self.removeItem(item._canvasItem)
|
||||||
|
else:
|
||||||
|
self.view.removeItem(item)
|
||||||
|
|
||||||
## disconnect signals, remove from list, etc..
|
## disconnect signals, remove from list, etc..
|
||||||
|
|
||||||
|
@ -11,14 +11,14 @@ class ArrowItem(QtGui.QGraphicsPolygonItem):
|
|||||||
|
|
||||||
|
|
||||||
def __init__(self, **opts):
|
def __init__(self, **opts):
|
||||||
QtGui.QGraphicsPolygonItem.__init__(self)
|
QtGui.QGraphicsPolygonItem.__init__(self, opts.get('parent', None))
|
||||||
defOpts = {
|
defOpts = {
|
||||||
'style': 'tri',
|
'style': 'tri',
|
||||||
'pxMode': True,
|
'pxMode': True,
|
||||||
'size': 20,
|
'size': 20,
|
||||||
'angle': -150,
|
'angle': -150, ## If the angle is 0, the arrow points left
|
||||||
'pos': (0,0),
|
'pos': (0,0),
|
||||||
'width': 8,
|
'width': None, ## width is automatically size / 2.
|
||||||
'tipAngle': 25,
|
'tipAngle': 25,
|
||||||
'baseAngle': 90,
|
'baseAngle': 90,
|
||||||
'pen': (200,200,200),
|
'pen': (200,200,200),
|
||||||
@ -38,10 +38,15 @@ class ArrowItem(QtGui.QGraphicsPolygonItem):
|
|||||||
self.opts = opts
|
self.opts = opts
|
||||||
|
|
||||||
if opts['style'] == 'tri':
|
if opts['style'] == 'tri':
|
||||||
|
if opts['width'] is None:
|
||||||
|
width = opts['size'] / 2.
|
||||||
|
else:
|
||||||
|
width = opts['width']
|
||||||
|
|
||||||
points = [
|
points = [
|
||||||
QtCore.QPointF(0,0),
|
QtCore.QPointF(0,0),
|
||||||
QtCore.QPointF(opts['size'],-opts['width']/2.),
|
QtCore.QPointF(opts['size'],-width/2.),
|
||||||
QtCore.QPointF(opts['size'],opts['width']/2.),
|
QtCore.QPointF(opts['size'],width/2.),
|
||||||
]
|
]
|
||||||
poly = QtGui.QPolygonF(points)
|
poly = QtGui.QPolygonF(points)
|
||||||
|
|
||||||
|
@ -284,7 +284,7 @@ class AxisItem(GraphicsWidget):
|
|||||||
lengthInPixels = Point(points[1] - points[0]).length()
|
lengthInPixels = Point(points[1] - points[0]).length()
|
||||||
|
|
||||||
## decide optimal tick spacing in pixels
|
## decide optimal tick spacing in pixels
|
||||||
pixelSpacing = np.log(lengthInPixels+10) * 3
|
pixelSpacing = np.log(lengthInPixels+10) * 2
|
||||||
optimalTickCount = lengthInPixels / pixelSpacing
|
optimalTickCount = lengthInPixels / pixelSpacing
|
||||||
|
|
||||||
## Determine optimal tick spacing
|
## Determine optimal tick spacing
|
||||||
@ -328,9 +328,11 @@ class AxisItem(GraphicsWidget):
|
|||||||
## draw three different intervals, long ticks first
|
## draw three different intervals, long ticks first
|
||||||
texts = []
|
texts = []
|
||||||
for i in [2,1,0]:
|
for i in [2,1,0]:
|
||||||
if i1+i > len(intervals):
|
if i1+i >= len(intervals) or i1+i < 0:
|
||||||
|
print "AxisItem.paint error: i1=%d, i=%d, len(intervals)=%d" % (i1, i, len(intervals))
|
||||||
continue
|
continue
|
||||||
## spacing for this interval
|
## spacing for this interval
|
||||||
|
|
||||||
sp = pw*intervals[i1+i]
|
sp = pw*intervals[i1+i]
|
||||||
|
|
||||||
## determine starting tick
|
## determine starting tick
|
||||||
|
@ -37,7 +37,8 @@ def rectStr(r):
|
|||||||
|
|
||||||
class ROI(GraphicsObject):
|
class ROI(GraphicsObject):
|
||||||
"""Generic region-of-interest widget.
|
"""Generic region-of-interest widget.
|
||||||
Can be used for implementing many types of selection box with rotate/translate/scale handles."""
|
Can be used for implementing many types of selection box with rotate/translate/scale handles.
|
||||||
|
"""
|
||||||
|
|
||||||
sigRegionChangeFinished = QtCore.Signal(object)
|
sigRegionChangeFinished = QtCore.Signal(object)
|
||||||
sigRegionChangeStarted = QtCore.Signal(object)
|
sigRegionChangeStarted = QtCore.Signal(object)
|
||||||
@ -53,6 +54,8 @@ class ROI(GraphicsObject):
|
|||||||
self.translatable = movable
|
self.translatable = movable
|
||||||
self.rotateAllowed = True
|
self.rotateAllowed = True
|
||||||
|
|
||||||
|
self.freeHandleMoved = False ## keep track of whether free handles have moved since last change signal was emitted.
|
||||||
|
|
||||||
if pen is None:
|
if pen is None:
|
||||||
pen = (255, 255, 255)
|
pen = (255, 255, 255)
|
||||||
self.setPen(pen)
|
self.setPen(pen)
|
||||||
@ -78,29 +81,33 @@ class ROI(GraphicsObject):
|
|||||||
#self.setFlag(self.ItemIsSelectable, True)
|
#self.setFlag(self.ItemIsSelectable, True)
|
||||||
|
|
||||||
def getState(self):
|
def getState(self):
|
||||||
return self.state.copy()
|
return self.stateCopy()
|
||||||
|
|
||||||
|
def stateCopy(self):
|
||||||
|
sc = {}
|
||||||
|
sc['pos'] = Point(self.state['pos'])
|
||||||
|
sc['size'] = Point(self.state['size'])
|
||||||
|
sc['angle'] = self.state['angle']
|
||||||
|
return sc
|
||||||
|
|
||||||
def saveState(self):
|
def saveState(self):
|
||||||
"""Return the state of the widget in a format suitable for storing to disk."""
|
"""Return the state of the widget in a format suitable for storing to disk. (Points are converted to tuple)"""
|
||||||
state = {}
|
state = {}
|
||||||
state['pos'] = tuple(self.state['pos'])
|
state['pos'] = tuple(self.state['pos'])
|
||||||
state['size'] = tuple(self.state['size'])
|
state['size'] = tuple(self.state['size'])
|
||||||
state['angle'] = self.state['angle']
|
state['angle'] = self.state['angle']
|
||||||
return state
|
return state
|
||||||
|
|
||||||
def setState(self, state):
|
def setState(self, state, update=True):
|
||||||
self.setPos(state['pos'], update=False)
|
self.setPos(state['pos'], update=False)
|
||||||
self.setSize(state['size'], update=False)
|
self.setSize(state['size'], update=False)
|
||||||
self.setAngle(state['angle'])
|
self.setAngle(state['angle'], update=update)
|
||||||
|
|
||||||
def setZValue(self, z):
|
def setZValue(self, z):
|
||||||
QtGui.QGraphicsItem.setZValue(self, z)
|
QtGui.QGraphicsItem.setZValue(self, z)
|
||||||
for h in self.handles:
|
for h in self.handles:
|
||||||
h['item'].setZValue(z+1)
|
h['item'].setZValue(z+1)
|
||||||
|
|
||||||
def sceneBounds(self):
|
|
||||||
return self.sceneTransform().mapRect(self.boundingRect())
|
|
||||||
|
|
||||||
def parentBounds(self):
|
def parentBounds(self):
|
||||||
return self.mapToParent(self.boundingRect()).boundingRect()
|
return self.mapToParent(self.boundingRect()).boundingRect()
|
||||||
|
|
||||||
@ -118,32 +125,121 @@ class ROI(GraphicsObject):
|
|||||||
def angle(self):
|
def angle(self):
|
||||||
return self.getState()['angle']
|
return self.getState()['angle']
|
||||||
|
|
||||||
def setPos(self, pos, update=True):
|
def setPos(self, pos, update=True, finish=True):
|
||||||
#print "setPos() called."
|
"""Set the position of the ROI (in the parent's coordinate system).
|
||||||
|
By default, this will cause both sigStateChanged and sigStateChangeFinished to be emitted.
|
||||||
|
|
||||||
|
If finish is False, then sigStateChangeFinished will not be emitted. You can then use
|
||||||
|
stateChangeFinished() to cause the signal to be emitted after a series of state changes.
|
||||||
|
|
||||||
|
If update is False, the state change will be remembered but not processed and no signals
|
||||||
|
will be emitted. You can then use stateChanged() to complete the state change. This allows
|
||||||
|
multiple change functions to be called sequentially while minimizing processing overhead
|
||||||
|
and repeated signals. Setting update=False also forces finish=False.
|
||||||
|
"""
|
||||||
|
|
||||||
pos = Point(pos)
|
pos = Point(pos)
|
||||||
self.state['pos'] = pos
|
self.state['pos'] = pos
|
||||||
QtGui.QGraphicsItem.setPos(self, pos)
|
QtGui.QGraphicsItem.setPos(self, pos)
|
||||||
if update:
|
if update:
|
||||||
self.updateHandles()
|
self.stateChanged(finish=finish)
|
||||||
self.handleChange()
|
|
||||||
|
|
||||||
def setSize(self, size, update=True):
|
def setSize(self, size, update=True, finish=True):
|
||||||
|
"""Set the size of the ROI. May be specified as a QPoint, Point, or list of two values.
|
||||||
|
See setPos() for an explanation of the update and finish arguments.
|
||||||
|
"""
|
||||||
size = Point(size)
|
size = Point(size)
|
||||||
self.prepareGeometryChange()
|
self.prepareGeometryChange()
|
||||||
self.state['size'] = size
|
self.state['size'] = size
|
||||||
if update:
|
if update:
|
||||||
self.updateHandles()
|
self.stateChanged(finish=finish)
|
||||||
self.handleChange()
|
|
||||||
|
|
||||||
def setAngle(self, angle, update=True):
|
def setAngle(self, angle, update=True, finish=True):
|
||||||
|
"""Set the angle of rotation (in degrees) for this ROI.
|
||||||
|
See setPos() for an explanation of the update and finish arguments.
|
||||||
|
"""
|
||||||
self.state['angle'] = angle
|
self.state['angle'] = angle
|
||||||
tr = QtGui.QTransform()
|
tr = QtGui.QTransform()
|
||||||
#tr.rotate(-angle * 180 / np.pi)
|
#tr.rotate(-angle * 180 / np.pi)
|
||||||
tr.rotate(angle)
|
tr.rotate(angle)
|
||||||
self.setTransform(tr)
|
self.setTransform(tr)
|
||||||
if update:
|
if update:
|
||||||
self.updateHandles()
|
self.stateChanged(finish=finish)
|
||||||
self.handleChange()
|
|
||||||
|
def scale(self, s, center=[0,0], update=True, finish=True):
|
||||||
|
"""
|
||||||
|
Resize the ROI by scaling relative to *center*.
|
||||||
|
See setPos() for an explanation of the *update* and *finish* arguments.
|
||||||
|
"""
|
||||||
|
c = self.mapToScene(Point(center) * self.state['size'])
|
||||||
|
self.prepareGeometryChange()
|
||||||
|
newSize = self.state['size'] * s
|
||||||
|
c1 = self.mapToScene(Point(center) * newSize)
|
||||||
|
newPos = self.state['pos'] + c - c1
|
||||||
|
|
||||||
|
self.setSize(newSize, update=False)
|
||||||
|
self.setPos(self.state['pos'], update=update, finish=finish)
|
||||||
|
|
||||||
|
|
||||||
|
def translate(self, *args, **kargs):
|
||||||
|
"""
|
||||||
|
Move the ROI to a new position.
|
||||||
|
Accepts either (x, y, snap) or ([x,y], snap) as arguments
|
||||||
|
If the ROI is bounded and the move would exceed boundaries, then the ROI
|
||||||
|
is moved to the nearest acceptable position instead.
|
||||||
|
|
||||||
|
snap can be:
|
||||||
|
None (default): use self.translateSnap and self.snapSize to determine whether/how to snap
|
||||||
|
False: do not snap
|
||||||
|
Point(w,h) snap to rectangular grid with spacing (w,h)
|
||||||
|
True: snap using self.snapSize (and ignoring self.translateSnap)
|
||||||
|
|
||||||
|
Also accepts *update* and *finish* arguments (see setPos() for a description of these).
|
||||||
|
"""
|
||||||
|
|
||||||
|
if len(args) == 1:
|
||||||
|
pt = args[0]
|
||||||
|
else:
|
||||||
|
pt = args
|
||||||
|
|
||||||
|
newState = self.stateCopy()
|
||||||
|
newState['pos'] = newState['pos'] + pt
|
||||||
|
|
||||||
|
## snap position
|
||||||
|
#snap = kargs.get('snap', None)
|
||||||
|
#if (snap is not False) and not (snap is None and self.translateSnap is False):
|
||||||
|
|
||||||
|
snap = kargs.get('snap', None)
|
||||||
|
if snap is None:
|
||||||
|
snap = self.translateSnap
|
||||||
|
if snap is not False:
|
||||||
|
newState['pos'] = self.getSnapPosition(newState['pos'], snap=snap)
|
||||||
|
|
||||||
|
#d = ev.scenePos() - self.mapToScene(self.pressPos)
|
||||||
|
if self.maxBounds is not None:
|
||||||
|
r = self.stateRect(newState)
|
||||||
|
#r0 = self.sceneTransform().mapRect(self.boundingRect())
|
||||||
|
d = Point(0,0)
|
||||||
|
if self.maxBounds.left() > r.left():
|
||||||
|
d[0] = self.maxBounds.left() - r.left()
|
||||||
|
elif self.maxBounds.right() < r.right():
|
||||||
|
d[0] = self.maxBounds.right() - r.right()
|
||||||
|
if self.maxBounds.top() > r.top():
|
||||||
|
d[1] = self.maxBounds.top() - r.top()
|
||||||
|
elif self.maxBounds.bottom() < r.bottom():
|
||||||
|
d[1] = self.maxBounds.bottom() - r.bottom()
|
||||||
|
newState['pos'] += d
|
||||||
|
|
||||||
|
#self.state['pos'] = newState['pos']
|
||||||
|
update = kargs.get('update', True)
|
||||||
|
finish = kargs.get('finish', True)
|
||||||
|
self.setPos(newState['pos'], update=update, finish=finish)
|
||||||
|
#if 'update' not in kargs or kargs['update'] is True:
|
||||||
|
#self.stateChanged()
|
||||||
|
|
||||||
|
def rotate(self, angle, center=(0,0), angleSnap=False, update=True, finish=True):
|
||||||
|
pass
|
||||||
|
#self.setAngle(self.angle()+angle, update=update, finish=finish)
|
||||||
|
|
||||||
|
|
||||||
def addTranslateHandle(self, pos, axes=None, item=None, name=None):
|
def addTranslateHandle(self, pos, axes=None, item=None, name=None):
|
||||||
@ -236,47 +332,6 @@ class ROI(GraphicsObject):
|
|||||||
for h in self.handles:
|
for h in self.handles:
|
||||||
h['item'].hide()
|
h['item'].hide()
|
||||||
|
|
||||||
#def mousePressEvent(self, ev):
|
|
||||||
### Bug: sometimes we get events we shouldn't.
|
|
||||||
#p = ev.pos()
|
|
||||||
#if not self.isMoving and not self.shape().contains(p):
|
|
||||||
#ev.ignore()
|
|
||||||
#return
|
|
||||||
#if ev.button() == QtCore.Qt.LeftButton:
|
|
||||||
#self.setSelected(True)
|
|
||||||
#if self.translatable:
|
|
||||||
#self.isMoving = True
|
|
||||||
#self.preMoveState = self.getState()
|
|
||||||
#self.cursorOffset = self.scenePos() - ev.scenePos()
|
|
||||||
##self.emit(QtCore.SIGNAL('regionChangeStarted'), self)
|
|
||||||
#self.sigRegionChangeStarted.emit(self)
|
|
||||||
#ev.accept()
|
|
||||||
#else:
|
|
||||||
#ev.ignore()
|
|
||||||
#elif ev.button() == QtCore.Qt.RightButton:
|
|
||||||
#if self.isMoving:
|
|
||||||
#ev.accept()
|
|
||||||
#self.cancelMove()
|
|
||||||
#else:
|
|
||||||
#ev.ignore()
|
|
||||||
#else:
|
|
||||||
#ev.ignore()
|
|
||||||
|
|
||||||
#def mouseMoveEvent(self, ev):
|
|
||||||
##print "mouse move", ev.pos()
|
|
||||||
#if self.translatable and self.isMoving and ev.buttons() == QtCore.Qt.LeftButton:
|
|
||||||
#snap = True if (ev.modifiers() & QtCore.Qt.ControlModifier) else None
|
|
||||||
##if self.translateSnap or (ev.modifiers() & QtCore.Qt.ControlModifier):
|
|
||||||
##snap = Point(self.snapSize, self.snapSize)
|
|
||||||
#newPos = ev.scenePos() + self.cursorOffset
|
|
||||||
#newPos = self.mapSceneToParent(newPos)
|
|
||||||
#self.translate(newPos - self.pos(), snap=snap)
|
|
||||||
|
|
||||||
#def mouseReleaseEvent(self, ev):
|
|
||||||
#if self.translatable:
|
|
||||||
#self.isMoving = False
|
|
||||||
##self.emit(QtCore.SIGNAL('regionChangeFinished'), self)
|
|
||||||
#self.sigRegionChangeFinished.emit(self)
|
|
||||||
|
|
||||||
def hoverEvent(self, ev):
|
def hoverEvent(self, ev):
|
||||||
if self.translatable and (not ev.isExit()) and ev.acceptDrags(QtCore.Qt.LeftButton):
|
if self.translatable and (not ev.isExit()) and ev.acceptDrags(QtCore.Qt.LeftButton):
|
||||||
@ -288,7 +343,7 @@ class ROI(GraphicsObject):
|
|||||||
|
|
||||||
def mouseDragEvent(self, ev):
|
def mouseDragEvent(self, ev):
|
||||||
if ev.isStart():
|
if ev.isStart():
|
||||||
p = ev.pos()
|
#p = ev.pos()
|
||||||
#if not self.isMoving and not self.shape().contains(p):
|
#if not self.isMoving and not self.shape().contains(p):
|
||||||
#ev.ignore()
|
#ev.ignore()
|
||||||
#return
|
#return
|
||||||
@ -298,7 +353,6 @@ class ROI(GraphicsObject):
|
|||||||
self.isMoving = True
|
self.isMoving = True
|
||||||
self.preMoveState = self.getState()
|
self.preMoveState = self.getState()
|
||||||
self.cursorOffset = self.pos() - self.mapToParent(ev.buttonDownPos())
|
self.cursorOffset = self.pos() - self.mapToParent(ev.buttonDownPos())
|
||||||
#self.emit(QtCore.SIGNAL('regionChangeStarted'), self)
|
|
||||||
self.sigRegionChangeStarted.emit(self)
|
self.sigRegionChangeStarted.emit(self)
|
||||||
ev.accept()
|
ev.accept()
|
||||||
else:
|
else:
|
||||||
@ -306,20 +360,15 @@ class ROI(GraphicsObject):
|
|||||||
|
|
||||||
elif ev.isFinish():
|
elif ev.isFinish():
|
||||||
if self.translatable:
|
if self.translatable:
|
||||||
|
if self.isMoving:
|
||||||
|
self.stateChangeFinished()
|
||||||
self.isMoving = False
|
self.isMoving = False
|
||||||
#self.emit(QtCore.SIGNAL('regionChangeFinished'), self)
|
|
||||||
self.sigRegionChangeFinished.emit(self)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.translatable and self.isMoving and ev.buttons() == QtCore.Qt.LeftButton:
|
if self.translatable and self.isMoving and ev.buttons() == QtCore.Qt.LeftButton:
|
||||||
snap = True if (ev.modifiers() & QtCore.Qt.ControlModifier) else None
|
snap = True if (ev.modifiers() & QtCore.Qt.ControlModifier) else None
|
||||||
#if self.translateSnap or (ev.modifiers() & QtCore.Qt.ControlModifier):
|
|
||||||
#snap = Point(self.snapSize, self.snapSize)
|
|
||||||
newPos = self.mapToParent(ev.pos()) + self.cursorOffset
|
newPos = self.mapToParent(ev.pos()) + self.cursorOffset
|
||||||
#newPos = self.mapSceneToParent(newPos)
|
self.translate(newPos - self.pos(), snap=snap, finish=False)
|
||||||
self.translate(newPos - self.pos(), snap=snap)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def mouseClickEvent(self, ev):
|
def mouseClickEvent(self, ev):
|
||||||
if ev.button() == QtCore.Qt.RightButton:
|
if ev.button() == QtCore.Qt.RightButton:
|
||||||
@ -329,24 +378,24 @@ class ROI(GraphicsObject):
|
|||||||
else:
|
else:
|
||||||
ev.ignore()
|
ev.ignore()
|
||||||
|
|
||||||
|
|
||||||
def cancelMove(self):
|
def cancelMove(self):
|
||||||
self.isMoving = False
|
self.isMoving = False
|
||||||
self.setState(self.preMoveState)
|
self.setState(self.preMoveState)
|
||||||
|
|
||||||
|
|
||||||
def pointDragEvent(self, pt, ev):
|
#def pointDragEvent(self, pt, ev):
|
||||||
if ev.isStart():
|
### just for handling drag start/stop.
|
||||||
self.isMoving = True
|
### drag moves are handled through movePoint()
|
||||||
self.preMoveState = self.getState()
|
|
||||||
|
|
||||||
self.sigRegionChangeStarted.emit(self)
|
#if ev.isStart():
|
||||||
elif ev.isFinish():
|
#self.isMoving = True
|
||||||
self.isMoving = False
|
#self.preMoveState = self.getState()
|
||||||
self.sigRegionChangeFinished.emit(self)
|
|
||||||
return
|
|
||||||
|
|
||||||
#self.movePoint(pt, ev.scenePos(), ev.modifiers())
|
#self.sigRegionChangeStarted.emit(self)
|
||||||
|
#elif ev.isFinish():
|
||||||
|
#self.isMoving = False
|
||||||
|
#self.sigRegionChangeFinished.emit(self)
|
||||||
|
#return
|
||||||
|
|
||||||
|
|
||||||
#def pointPressEvent(self, pt, ev):
|
#def pointPressEvent(self, pt, ev):
|
||||||
@ -368,37 +417,20 @@ class ROI(GraphicsObject):
|
|||||||
#def pointMoveEvent(self, pt, ev):
|
#def pointMoveEvent(self, pt, ev):
|
||||||
#self.movePoint(pt, ev.scenePos(), ev.modifiers())
|
#self.movePoint(pt, ev.scenePos(), ev.modifiers())
|
||||||
|
|
||||||
def stateCopy(self):
|
|
||||||
sc = {}
|
|
||||||
sc['pos'] = Point(self.state['pos'])
|
|
||||||
sc['size'] = Point(self.state['size'])
|
|
||||||
sc['angle'] = self.state['angle']
|
|
||||||
return sc
|
|
||||||
|
|
||||||
def updateHandles(self):
|
|
||||||
#print "update", self.handles
|
|
||||||
for h in self.handles:
|
|
||||||
#print " try", h
|
|
||||||
if h['item'] in self.childItems():
|
|
||||||
p = h['pos']
|
|
||||||
#print h['pos'] * self.state['size']
|
|
||||||
h['item'].setPos(h['pos'] * self.state['size'])
|
|
||||||
#else:
|
|
||||||
#print " Not child!", self.childItems()
|
|
||||||
|
|
||||||
|
|
||||||
def checkPointMove(self, pt, pos, modifiers):
|
def checkPointMove(self, pt, pos, modifiers):
|
||||||
|
"""When handles move, they must ask the ROI if the move is acceptable.
|
||||||
|
By default, this always returns True. Subclasses may wish override.
|
||||||
|
"""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def movePoint(self, pt, pos, modifiers=QtCore.Qt.KeyboardModifier()):
|
def movePoint(self, pt, pos, modifiers=QtCore.Qt.KeyboardModifier(), finish=True):
|
||||||
#print "movePoint() called."
|
## called by Handles when they are moved.
|
||||||
## pos is the new position of the handle in scene coords, as requested by the handle.
|
## pos is the new position of the handle in scene coords, as requested by the handle.
|
||||||
|
|
||||||
newState = self.stateCopy()
|
newState = self.stateCopy()
|
||||||
h = self.handles[pt]
|
h = self.handles[pt]
|
||||||
#p0 = self.mapToScene(h['item'].pos())
|
|
||||||
## p0 is current (before move) position of handle in scene coords
|
|
||||||
p0 = self.mapToScene(h['pos'] * self.state['size'])
|
p0 = self.mapToScene(h['pos'] * self.state['size'])
|
||||||
p1 = Point(pos)
|
p1 = Point(pos)
|
||||||
|
|
||||||
@ -410,15 +442,10 @@ class ROI(GraphicsObject):
|
|||||||
if h.has_key('center'):
|
if h.has_key('center'):
|
||||||
c = h['center']
|
c = h['center']
|
||||||
cs = c * self.state['size']
|
cs = c * self.state['size']
|
||||||
#lpOrig = h['pos'] -
|
|
||||||
#lp0 = self.mapFromScene(p0) - cs
|
|
||||||
#lp1 = self.mapFromScene(p1) - cs
|
|
||||||
lp0 = self.mapFromParent(p0) - cs
|
lp0 = self.mapFromParent(p0) - cs
|
||||||
lp1 = self.mapFromParent(p1) - cs
|
lp1 = self.mapFromParent(p1) - cs
|
||||||
|
|
||||||
if h['type'] == 't':
|
if h['type'] == 't':
|
||||||
#p0 = Point(self.mapToScene(h['item'].pos()))
|
|
||||||
#p1 = Point(pos + self.mapToScene(self.pressHandlePos) - self.mapToScene(self.pressPos))
|
|
||||||
snap = True if (modifiers & QtCore.Qt.ControlModifier) else None
|
snap = True if (modifiers & QtCore.Qt.ControlModifier) else None
|
||||||
#if self.translateSnap or ():
|
#if self.translateSnap or ():
|
||||||
#snap = Point(self.snapSize, self.snapSize)
|
#snap = Point(self.snapSize, self.snapSize)
|
||||||
@ -426,14 +453,10 @@ class ROI(GraphicsObject):
|
|||||||
|
|
||||||
elif h['type'] == 'f':
|
elif h['type'] == 'f':
|
||||||
h['item'].setPos(self.mapFromScene(pos))
|
h['item'].setPos(self.mapFromScene(pos))
|
||||||
#self.emit(QtCore.SIGNAL('regionChanged'), self)
|
self.freeHandleMoved = True
|
||||||
self.sigRegionChanged.emit(self)
|
#self.sigRegionChanged.emit(self) ## should be taken care of by call to stateChanged()
|
||||||
|
|
||||||
elif h['type'] == 's':
|
elif h['type'] == 's':
|
||||||
#c = h['center']
|
|
||||||
#cs = c * self.state['size']
|
|
||||||
#p1 = (self.mapFromScene(ev.scenePos()) + self.pressHandlePos - self.pressPos) - cs
|
|
||||||
|
|
||||||
## If a handle and its center have the same x or y value, we can't scale across that axis.
|
## If a handle and its center have the same x or y value, we can't scale across that axis.
|
||||||
if h['center'][0] == h['pos'][0]:
|
if h['center'][0] == h['pos'][0]:
|
||||||
lp1[0] = 0
|
lp1[0] = 0
|
||||||
@ -485,13 +508,12 @@ class ROI(GraphicsObject):
|
|||||||
return
|
return
|
||||||
|
|
||||||
self.setPos(newState['pos'], update=False)
|
self.setPos(newState['pos'], update=False)
|
||||||
self.prepareGeometryChange()
|
self.setSize(newState['size'], update=False)
|
||||||
self.state = newState
|
|
||||||
|
|
||||||
## move handles to their new locations
|
|
||||||
self.updateHandles()
|
|
||||||
|
|
||||||
elif h['type'] in ['r', 'rf']:
|
elif h['type'] in ['r', 'rf']:
|
||||||
|
if h['type'] == 'rf':
|
||||||
|
self.freeHandleMoved = True
|
||||||
|
|
||||||
if not self.rotateAllowed:
|
if not self.rotateAllowed:
|
||||||
return
|
return
|
||||||
## If the handle is directly over its center point, we can't compute an angle.
|
## If the handle is directly over its center point, we can't compute an angle.
|
||||||
@ -507,10 +529,9 @@ class ROI(GraphicsObject):
|
|||||||
|
|
||||||
## create rotation transform
|
## create rotation transform
|
||||||
tr = QtGui.QTransform()
|
tr = QtGui.QTransform()
|
||||||
#tr.rotate(-ang * 180. / np.pi)
|
|
||||||
tr.rotate(ang)
|
tr.rotate(ang)
|
||||||
|
|
||||||
## mvoe ROI so that center point remains stationary after rotate
|
## move ROI so that center point remains stationary after rotate
|
||||||
cc = self.mapToParent(cs) - (tr.map(cs) + self.state['pos'])
|
cc = self.mapToParent(cs) - (tr.map(cs) + self.state['pos'])
|
||||||
newState['angle'] = ang
|
newState['angle'] = ang
|
||||||
newState['pos'] = newState['pos'] + cc
|
newState['pos'] = newState['pos'] + cc
|
||||||
@ -520,60 +541,22 @@ class ROI(GraphicsObject):
|
|||||||
r = self.stateRect(newState)
|
r = self.stateRect(newState)
|
||||||
if not self.maxBounds.contains(r):
|
if not self.maxBounds.contains(r):
|
||||||
return
|
return
|
||||||
self.setTransform(tr)
|
#self.setTransform(tr)
|
||||||
self.setPos(newState['pos'], update=False)
|
self.setPos(newState['pos'], update=False)
|
||||||
self.state = newState
|
self.setAngle(ang, update=False)
|
||||||
|
#self.state = newState
|
||||||
|
|
||||||
## If this is a free-rotate handle, its distance from the center may change.
|
## If this is a free-rotate handle, its distance from the center may change.
|
||||||
|
|
||||||
if h['type'] == 'rf':
|
if h['type'] == 'rf':
|
||||||
h['item'].setPos(self.mapFromScene(p1)) ## changes ROI coordinates of handle
|
h['item'].setPos(self.mapFromScene(p1)) ## changes ROI coordinates of handle
|
||||||
|
|
||||||
|
|
||||||
#elif h['type'] == 'rf':
|
|
||||||
### If the handle is directly over its center point, we can't compute an angle.
|
|
||||||
#if lp1.length() == 0 or lp0.length() == 0:
|
|
||||||
#return
|
|
||||||
|
|
||||||
### determine new rotation angle, constrained if necessary
|
|
||||||
#pos = Point(pos)
|
|
||||||
#ang = newState['angle'] + lp0.angle(lp1)
|
|
||||||
#if ang is None:
|
|
||||||
##h['item'].setPos(self.mapFromScene(Point(pos[0], 0.0))) ## changes ROI coordinates of handle
|
|
||||||
#h['item'].setPos(self.mapFromScene(pos))
|
|
||||||
#return
|
|
||||||
#if self.rotateSnap or (modifiers & QtCore.Qt.ControlModifier):
|
|
||||||
#ang = round(ang / (np.pi/12.)) * (np.pi/12.)
|
|
||||||
|
|
||||||
|
|
||||||
#tr = QtGui.QTransform()
|
|
||||||
#tr.rotate(-ang * 180. / np.pi)
|
|
||||||
|
|
||||||
#cc = self.mapToParent(cs) - (tr.map(cs) + self.state['pos'])
|
|
||||||
#newState['angle'] = ang
|
|
||||||
#newState['pos'] = newState['pos'] + cc
|
|
||||||
#if self.maxBounds is not None:
|
|
||||||
#r = self.stateRect(newState)
|
|
||||||
#if not self.maxBounds.contains(r):
|
|
||||||
#return
|
|
||||||
#self.setTransform(tr)
|
|
||||||
#self.setPos(newState['pos'], update=False)
|
|
||||||
#self.state = newState
|
|
||||||
|
|
||||||
#h['item'].setPos(self.mapFromScene(pos)) ## changes ROI coordinates of handle
|
|
||||||
##self.emit(QtCore.SIGNAL('regionChanged'), self)
|
|
||||||
|
|
||||||
elif h['type'] == 'sr':
|
elif h['type'] == 'sr':
|
||||||
#newState = self.stateCopy()
|
|
||||||
if h['center'][0] == h['pos'][0]:
|
if h['center'][0] == h['pos'][0]:
|
||||||
scaleAxis = 1
|
scaleAxis = 1
|
||||||
else:
|
else:
|
||||||
scaleAxis = 0
|
scaleAxis = 0
|
||||||
|
|
||||||
#c = h['center']
|
|
||||||
#cs = c * self.state['size']
|
|
||||||
#p0 = Point(h['item'].pos()) - cs
|
|
||||||
#p1 = (self.mapFromScene(ev.scenePos()) + self.pressHandlePos - self.pressPos) - cs
|
|
||||||
if lp1.length() == 0 or lp0.length() == 0:
|
if lp1.length() == 0 or lp0.length() == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -586,14 +569,14 @@ class ROI(GraphicsObject):
|
|||||||
|
|
||||||
hs = abs(h['pos'][scaleAxis] - c[scaleAxis])
|
hs = abs(h['pos'][scaleAxis] - c[scaleAxis])
|
||||||
newState['size'][scaleAxis] = lp1.length() / hs
|
newState['size'][scaleAxis] = lp1.length() / hs
|
||||||
if self.scaleSnap or (modifiers & QtCore.Qt.ControlModifier):
|
#if self.scaleSnap or (modifiers & QtCore.Qt.ControlModifier):
|
||||||
|
if self.scaleSnap: ## use CTRL only for angular snap here.
|
||||||
newState['size'][scaleAxis] = round(newState['size'][scaleAxis] / self.snapSize) * self.snapSize
|
newState['size'][scaleAxis] = round(newState['size'][scaleAxis] / self.snapSize) * self.snapSize
|
||||||
if newState['size'][scaleAxis] == 0:
|
if newState['size'][scaleAxis] == 0:
|
||||||
newState['size'][scaleAxis] = 1
|
newState['size'][scaleAxis] = 1
|
||||||
|
|
||||||
c1 = c * newState['size']
|
c1 = c * newState['size']
|
||||||
tr = QtGui.QTransform()
|
tr = QtGui.QTransform()
|
||||||
#tr.rotate(-ang * 180. / np.pi)
|
|
||||||
tr.rotate(ang)
|
tr.rotate(ang)
|
||||||
|
|
||||||
cc = self.mapToParent(cs) - (tr.map(c1) + self.state['pos'])
|
cc = self.mapToParent(cs) - (tr.map(c1) + self.state['pos'])
|
||||||
@ -603,94 +586,48 @@ class ROI(GraphicsObject):
|
|||||||
r = self.stateRect(newState)
|
r = self.stateRect(newState)
|
||||||
if not self.maxBounds.contains(r):
|
if not self.maxBounds.contains(r):
|
||||||
return
|
return
|
||||||
self.setTransform(tr)
|
#self.setTransform(tr)
|
||||||
self.setPos(newState['pos'], update=False)
|
#self.setPos(newState['pos'], update=False)
|
||||||
self.prepareGeometryChange()
|
#self.prepareGeometryChange()
|
||||||
self.state = newState
|
#self.state = newState
|
||||||
|
self.setState(newState, update=False)
|
||||||
|
|
||||||
self.updateHandles()
|
self.stateChanged(finish=finish)
|
||||||
|
|
||||||
self.handleChange()
|
def stateChanged(self, finish=True):
|
||||||
|
"""Process changes to the state of the ROI.
|
||||||
|
If there are any changes, then the positions of handles are updated accordingly
|
||||||
|
and sigRegionChanged is emitted. If finish is True, then
|
||||||
|
sigRegionChangeFinished will also be emitted."""
|
||||||
|
|
||||||
def handleChange(self):
|
|
||||||
"""The state of the ROI has changed; redraw if needed."""
|
|
||||||
#print "handleChange() called."
|
|
||||||
changed = False
|
changed = False
|
||||||
#print "self.lastState:", self.lastState
|
|
||||||
if self.lastState is None:
|
if self.lastState is None:
|
||||||
changed = True
|
changed = True
|
||||||
else:
|
else:
|
||||||
for k in self.state.keys():
|
for k in self.state.keys():
|
||||||
#print k, self.state[k], self.lastState[k]
|
|
||||||
if self.state[k] != self.lastState[k]:
|
if self.state[k] != self.lastState[k]:
|
||||||
#print "state %s has changed; emit signal" % k
|
|
||||||
changed = True
|
changed = True
|
||||||
self.lastState = self.stateCopy()
|
self.lastState = self.stateCopy()
|
||||||
#print "changed =", changed
|
|
||||||
if changed:
|
if changed:
|
||||||
#print "handle changed."
|
## Move all handles to match the current configuration of the ROI
|
||||||
|
for h in self.handles:
|
||||||
|
if h['item'] in self.childItems():
|
||||||
|
p = h['pos']
|
||||||
|
h['item'].setPos(h['pos'] * self.state['size'])
|
||||||
|
|
||||||
self.update()
|
self.update()
|
||||||
#self.emit(QtCore.SIGNAL('regionChanged'), self)
|
self.sigRegionChanged.emit(self)
|
||||||
|
elif self.freeHandleMoved:
|
||||||
self.sigRegionChanged.emit(self)
|
self.sigRegionChanged.emit(self)
|
||||||
|
|
||||||
|
self.freeHandleMoved = False
|
||||||
|
|
||||||
def scale(self, s, center=[0,0]):
|
if finish:
|
||||||
c = self.mapToScene(Point(center) * self.state['size'])
|
self.stateChangeFinished()
|
||||||
self.prepareGeometryChange()
|
|
||||||
self.state['size'] = self.state['size'] * s
|
|
||||||
c1 = self.mapToScene(Point(center) * self.state['size'])
|
|
||||||
self.state['pos'] = self.state['pos'] + c - c1
|
|
||||||
self.setPos(self.state['pos'])
|
|
||||||
self.updateHandles()
|
|
||||||
|
|
||||||
|
def stateChangeFinished(self):
|
||||||
def translate(self, *args, **kargs):
|
self.sigRegionChangeFinished.emit(self)
|
||||||
"""accepts either (x, y, snap) or ([x,y], snap) as arguments
|
|
||||||
|
|
||||||
snap can be:
|
|
||||||
None (default): use self.translateSnap and self.snapSize to determine whether/how to snap
|
|
||||||
False: do no snap
|
|
||||||
Point(w,h) snap to rectangular grid with spacing (w,h)
|
|
||||||
True: snap using self.snapSize (and ignoring self.translateSnap)
|
|
||||||
"""
|
|
||||||
|
|
||||||
if len(args) == 1:
|
|
||||||
pt = args[0]
|
|
||||||
else:
|
|
||||||
pt = args
|
|
||||||
|
|
||||||
newState = self.stateCopy()
|
|
||||||
newState['pos'] = newState['pos'] + pt
|
|
||||||
|
|
||||||
## snap position
|
|
||||||
#snap = kargs.get('snap', None)
|
|
||||||
#if (snap is not False) and not (snap is None and self.translateSnap is False):
|
|
||||||
|
|
||||||
snap = kargs.get('snap', None)
|
|
||||||
if snap is None:
|
|
||||||
snap = self.translateSnap
|
|
||||||
if snap is not False:
|
|
||||||
newState['pos'] = self.getSnapPosition(newState['pos'], snap=snap)
|
|
||||||
|
|
||||||
#d = ev.scenePos() - self.mapToScene(self.pressPos)
|
|
||||||
if self.maxBounds is not None:
|
|
||||||
r = self.stateRect(newState)
|
|
||||||
#r0 = self.sceneTransform().mapRect(self.boundingRect())
|
|
||||||
d = Point(0,0)
|
|
||||||
if self.maxBounds.left() > r.left():
|
|
||||||
d[0] = self.maxBounds.left() - r.left()
|
|
||||||
elif self.maxBounds.right() < r.right():
|
|
||||||
d[0] = self.maxBounds.right() - r.right()
|
|
||||||
if self.maxBounds.top() > r.top():
|
|
||||||
d[1] = self.maxBounds.top() - r.top()
|
|
||||||
elif self.maxBounds.bottom() < r.bottom():
|
|
||||||
d[1] = self.maxBounds.bottom() - r.bottom()
|
|
||||||
newState['pos'] += d
|
|
||||||
|
|
||||||
self.state['pos'] = newState['pos']
|
|
||||||
self.setPos(self.state['pos'])
|
|
||||||
#if 'update' not in kargs or kargs['update'] is True:
|
|
||||||
self.handleChange()
|
|
||||||
|
|
||||||
def stateRect(self, state):
|
def stateRect(self, state):
|
||||||
r = QtCore.QRectF(0, 0, state['size'][0], state['size'][1])
|
r = QtCore.QRectF(0, 0, state['size'][0], state['size'][1])
|
||||||
@ -950,166 +887,6 @@ class ROI(GraphicsObject):
|
|||||||
self.setState(st)
|
self.setState(st)
|
||||||
|
|
||||||
|
|
||||||
#class Handle(QtGui.QGraphicsItem):
|
|
||||||
|
|
||||||
#types = { ## defines number of sides, start angle for each handle type
|
|
||||||
#'t': (4, np.pi/4),
|
|
||||||
#'f': (4, np.pi/4),
|
|
||||||
#'s': (4, 0),
|
|
||||||
#'r': (12, 0),
|
|
||||||
#'sr': (12, 0),
|
|
||||||
#'rf': (12, 0),
|
|
||||||
#}
|
|
||||||
|
|
||||||
#def __init__(self, radius, typ=None, pen=(200, 200, 220), parent=None):
|
|
||||||
##print " create item with parent", parent
|
|
||||||
#self.bounds = QtCore.QRectF(-1e-10, -1e-10, 2e-10, 2e-10)
|
|
||||||
#QtGui.QGraphicsItem.__init__(self, parent)
|
|
||||||
#self.setFlags(self.flags() | self.ItemIgnoresTransformations | self.ItemSendsScenePositionChanges)
|
|
||||||
#self.setZValue(11)
|
|
||||||
#self.roi = []
|
|
||||||
#self.radius = radius
|
|
||||||
#self.typ = typ
|
|
||||||
#self.pen = fn.mkPen(pen)
|
|
||||||
#self.currentPen = self.pen
|
|
||||||
#self.pen.setWidth(0)
|
|
||||||
#self.pen.setCosmetic(True)
|
|
||||||
#self.isMoving = False
|
|
||||||
#self.sides, self.startAng = self.types[typ]
|
|
||||||
#self.buildPath()
|
|
||||||
#self.updateShape()
|
|
||||||
|
|
||||||
#def connectROI(self, roi, i):
|
|
||||||
#self.roi.append((roi, i))
|
|
||||||
|
|
||||||
##def boundingRect(self):
|
|
||||||
##return self.bounds
|
|
||||||
|
|
||||||
|
|
||||||
#def hoverEvent(self, ev):
|
|
||||||
#if (not ev.isExit()) and ev.acceptDrags(QtCore.Qt.LeftButton):
|
|
||||||
#self.currentPen = fn.mkPen(255, 0,0)
|
|
||||||
#else:
|
|
||||||
#self.currentPen = self.pen
|
|
||||||
#self.update()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#def mouseClickEvent(self, ev):
|
|
||||||
### right-click cancels drag
|
|
||||||
#if ev.button() == QtCore.Qt.RightButton and self.isMoving:
|
|
||||||
#self.isMoving = False ## prevents any further motion
|
|
||||||
#for r in self.roi:
|
|
||||||
#r[0].cancelMove()
|
|
||||||
#ev.accept()
|
|
||||||
|
|
||||||
|
|
||||||
#def mouseDragEvent(self, ev):
|
|
||||||
#if ev.button() != QtCore.Qt.LeftButton:
|
|
||||||
#return
|
|
||||||
#ev.accept()
|
|
||||||
|
|
||||||
### Inform ROIs that a drag is happening
|
|
||||||
### note: the ROI is informed that the handle has moved using ROI.movePoint
|
|
||||||
### this is for other (more nefarious) purposes.
|
|
||||||
#for r in self.roi:
|
|
||||||
#r[0].pointDragEvent(r[1], ev)
|
|
||||||
|
|
||||||
#if ev.isFinish():
|
|
||||||
#self.isMoving = False
|
|
||||||
#elif ev.isStart():
|
|
||||||
#self.isMoving = True
|
|
||||||
#self.cursorOffset = self.scenePos() - ev.buttonDownScenePos()
|
|
||||||
|
|
||||||
#if self.isMoving: ## note: isMoving may become False in mid-drag due to right-click.
|
|
||||||
#pos = ev.scenePos() + self.cursorOffset
|
|
||||||
#self.movePoint(pos, ev.modifiers())
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#def movePoint(self, pos, modifiers=QtCore.Qt.KeyboardModifier()):
|
|
||||||
#for r in self.roi:
|
|
||||||
#if not r[0].checkPointMove(r[1], pos, modifiers):
|
|
||||||
#return
|
|
||||||
##print "point moved; inform %d ROIs" % len(self.roi)
|
|
||||||
## A handle can be used by multiple ROIs; tell each to update its handle position
|
|
||||||
#for r in self.roi:
|
|
||||||
#r[0].movePoint(r[1], pos, modifiers)
|
|
||||||
|
|
||||||
#def buildPath(self):
|
|
||||||
#size = self.radius
|
|
||||||
#self.path = QtGui.QPainterPath()
|
|
||||||
#ang = self.startAng
|
|
||||||
#dt = 2*np.pi / self.sides
|
|
||||||
#for i in range(0, self.sides+1):
|
|
||||||
#x = size * cos(ang)
|
|
||||||
#y = size * sin(ang)
|
|
||||||
#ang += dt
|
|
||||||
#if i == 0:
|
|
||||||
#self.path.moveTo(x, y)
|
|
||||||
#else:
|
|
||||||
#self.path.lineTo(x, y)
|
|
||||||
|
|
||||||
#def paint(self, p, opt, widget):
|
|
||||||
#### determine rotation of transform
|
|
||||||
##m = self.sceneTransform()
|
|
||||||
###mi = m.inverted()[0]
|
|
||||||
##v = m.map(QtCore.QPointF(1, 0)) - m.map(QtCore.QPointF(0, 0))
|
|
||||||
##va = np.arctan2(v.y(), v.x())
|
|
||||||
|
|
||||||
#### Determine length of unit vector in painter's coords
|
|
||||||
###size = mi.map(Point(self.radius, self.radius)) - mi.map(Point(0, 0))
|
|
||||||
###size = (size.x()*size.x() + size.y() * size.y()) ** 0.5
|
|
||||||
##size = self.radius
|
|
||||||
|
|
||||||
##bounds = QtCore.QRectF(-size, -size, size*2, size*2)
|
|
||||||
##if bounds != self.bounds:
|
|
||||||
##self.bounds = bounds
|
|
||||||
##self.prepareGeometryChange()
|
|
||||||
#p.setRenderHints(p.Antialiasing, True)
|
|
||||||
#p.setPen(self.currentPen)
|
|
||||||
|
|
||||||
##p.rotate(va * 180. / 3.1415926)
|
|
||||||
##p.drawPath(self.path)
|
|
||||||
#p.drawPath(self.shape())
|
|
||||||
|
|
||||||
##ang = self.startAng + va
|
|
||||||
##dt = 2*np.pi / self.sides
|
|
||||||
##for i in range(0, self.sides):
|
|
||||||
##x1 = size * cos(ang)
|
|
||||||
##y1 = size * sin(ang)
|
|
||||||
##x2 = size * cos(ang+dt)
|
|
||||||
##y2 = size * sin(ang+dt)
|
|
||||||
##ang += dt
|
|
||||||
##p.drawLine(Point(x1, y1), Point(x2, y2))
|
|
||||||
|
|
||||||
#def shape(self):
|
|
||||||
#return self._shape
|
|
||||||
|
|
||||||
#def boundingRect(self):
|
|
||||||
#return self.shape().boundingRect()
|
|
||||||
|
|
||||||
#def updateShape(self):
|
|
||||||
### determine rotation of transform
|
|
||||||
#m = self.sceneTransform()
|
|
||||||
##mi = m.inverted()[0]
|
|
||||||
#v = m.map(QtCore.QPointF(1, 0)) - m.map(QtCore.QPointF(0, 0))
|
|
||||||
#va = np.arctan2(v.y(), v.x())
|
|
||||||
|
|
||||||
#tr = QtGui.QTransform()
|
|
||||||
#tr.rotate(va * 180. / 3.1415926)
|
|
||||||
##tr.scale(self.radius, self.radius)
|
|
||||||
#self._shape = tr.map(self.path)
|
|
||||||
#self.prepareGeometryChange()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#def itemChange(self, change, value):
|
|
||||||
#ret = QtGui.QGraphicsItem.itemChange(self, change, value)
|
|
||||||
#if change == self.ItemScenePositionHasChanged:
|
|
||||||
#self.updateShape()
|
|
||||||
#return ret
|
|
||||||
|
|
||||||
class Handle(UIGraphicsItem):
|
class Handle(UIGraphicsItem):
|
||||||
|
|
||||||
types = { ## defines number of sides, start angle for each handle type
|
types = { ## defines number of sides, start angle for each handle type
|
||||||
@ -1160,8 +937,9 @@ class Handle(UIGraphicsItem):
|
|||||||
## right-click cancels drag
|
## right-click cancels drag
|
||||||
if ev.button() == QtCore.Qt.RightButton and self.isMoving:
|
if ev.button() == QtCore.Qt.RightButton and self.isMoving:
|
||||||
self.isMoving = False ## prevents any further motion
|
self.isMoving = False ## prevents any further motion
|
||||||
for r in self.roi:
|
self.movePoint(self.startPos, finish=True)
|
||||||
r[0].cancelMove()
|
#for r in self.roi:
|
||||||
|
#r[0].cancelMove()
|
||||||
ev.accept()
|
ev.accept()
|
||||||
|
|
||||||
|
|
||||||
@ -1173,29 +951,31 @@ class Handle(UIGraphicsItem):
|
|||||||
## Inform ROIs that a drag is happening
|
## Inform ROIs that a drag is happening
|
||||||
## note: the ROI is informed that the handle has moved using ROI.movePoint
|
## note: the ROI is informed that the handle has moved using ROI.movePoint
|
||||||
## this is for other (more nefarious) purposes.
|
## this is for other (more nefarious) purposes.
|
||||||
for r in self.roi:
|
#for r in self.roi:
|
||||||
r[0].pointDragEvent(r[1], ev)
|
#r[0].pointDragEvent(r[1], ev)
|
||||||
|
|
||||||
if ev.isFinish():
|
if ev.isFinish():
|
||||||
|
if self.isMoving:
|
||||||
|
for r in self.roi:
|
||||||
|
r[0].stateChangeFinished()
|
||||||
self.isMoving = False
|
self.isMoving = False
|
||||||
elif ev.isStart():
|
elif ev.isStart():
|
||||||
self.isMoving = True
|
self.isMoving = True
|
||||||
|
self.startPos = self.scenePos()
|
||||||
self.cursorOffset = self.scenePos() - ev.buttonDownScenePos()
|
self.cursorOffset = self.scenePos() - ev.buttonDownScenePos()
|
||||||
|
|
||||||
if self.isMoving: ## note: isMoving may become False in mid-drag due to right-click.
|
if self.isMoving: ## note: isMoving may become False in mid-drag due to right-click.
|
||||||
pos = ev.scenePos() + self.cursorOffset
|
pos = ev.scenePos() + self.cursorOffset
|
||||||
self.movePoint(pos, ev.modifiers())
|
self.movePoint(pos, ev.modifiers(), finish=False)
|
||||||
|
|
||||||
|
def movePoint(self, pos, modifiers=QtCore.Qt.KeyboardModifier(), finish=True):
|
||||||
|
|
||||||
def movePoint(self, pos, modifiers=QtCore.Qt.KeyboardModifier()):
|
|
||||||
for r in self.roi:
|
for r in self.roi:
|
||||||
if not r[0].checkPointMove(r[1], pos, modifiers):
|
if not r[0].checkPointMove(r[1], pos, modifiers):
|
||||||
return
|
return
|
||||||
#print "point moved; inform %d ROIs" % len(self.roi)
|
#print "point moved; inform %d ROIs" % len(self.roi)
|
||||||
# A handle can be used by multiple ROIs; tell each to update its handle position
|
# A handle can be used by multiple ROIs; tell each to update its handle position
|
||||||
for r in self.roi:
|
for r in self.roi:
|
||||||
r[0].movePoint(r[1], pos, modifiers)
|
r[0].movePoint(r[1], pos, modifiers, finish=finish)
|
||||||
|
|
||||||
def buildPath(self):
|
def buildPath(self):
|
||||||
size = self.radius
|
size = self.radius
|
||||||
@ -1629,8 +1409,8 @@ class SpiralROI(ROI):
|
|||||||
for h in self.handles:
|
for h in self.handles:
|
||||||
h['pos'] = h['item'].pos()/self.state['size'][0]
|
h['pos'] = h['item'].pos()/self.state['size'][0]
|
||||||
|
|
||||||
def handleChange(self):
|
def stateChanged(self):
|
||||||
ROI.handleChange(self)
|
ROI.stateChanged(self)
|
||||||
if len(self.handles) > 1:
|
if len(self.handles) > 1:
|
||||||
self.path = QtGui.QPainterPath()
|
self.path = QtGui.QPainterPath()
|
||||||
h0 = Point(self.handles[0]['item'].pos()).length()
|
h0 = Point(self.handles[0]['item'].pos()).length()
|
||||||
|
@ -206,7 +206,10 @@ class ViewBox(GraphicsWidget):
|
|||||||
#print "addItem:", item, item.boundingRect()
|
#print "addItem:", item, item.boundingRect()
|
||||||
|
|
||||||
def removeItem(self, item):
|
def removeItem(self, item):
|
||||||
self.addedItems.remove(item)
|
try:
|
||||||
|
self.addedItems.remove(item)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
self.scene().removeItem(item)
|
self.scene().removeItem(item)
|
||||||
self.updateAutoRange()
|
self.updateAutoRange()
|
||||||
|
|
||||||
|
@ -23,9 +23,9 @@ from pyqtgraph.graphicsItems.ViewBox import *
|
|||||||
from pyqtgraph.Qt import QtCore, QtGui
|
from pyqtgraph.Qt import QtCore, QtGui
|
||||||
import sys
|
import sys
|
||||||
#from numpy import ndarray
|
#from numpy import ndarray
|
||||||
import ptime
|
import pyqtgraph.ptime as ptime
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import debug
|
import pyqtgraph.debug as debug
|
||||||
|
|
||||||
from pyqtgraph.SignalProxy import SignalProxy
|
from pyqtgraph.SignalProxy import SignalProxy
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ from pyqtgraph.Qt import QtCore, QtGui, QtOpenGL, QtSvg
|
|||||||
from pyqtgraph.Point import Point
|
from pyqtgraph.Point import Point
|
||||||
#from vector import *
|
#from vector import *
|
||||||
import sys, os
|
import sys, os
|
||||||
import debug
|
#import debug
|
||||||
from FileDialog import FileDialog
|
from FileDialog import FileDialog
|
||||||
from pyqtgraph.GraphicsScene import GraphicsScene
|
from pyqtgraph.GraphicsScene import GraphicsScene
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
Loading…
x
Reference in New Issue
Block a user