Signal cleanup:

- Renamed GraphicsView signals to avoid collision with ViewBox signals that
  are wrapped in PlotWidget: sigRangeChanged => sigDeviceRangeChanged and
  sigTransformChanged => sigDeviceTransformChanged.
- All signal disconnections that catch TypeError now also catch RuntimeError
  for pyside compatibility.
This commit is contained in:
Luke Campagnola 2014-02-07 10:38:41 -05:00
parent 8730245990
commit 193367a56b
10 changed files with 63 additions and 39 deletions

View File

@ -12,6 +12,9 @@ pyqtgraph-0.9.9 [unreleased]
- ImageItem is faster by avoiding makeQImage(transpose=True) - ImageItem is faster by avoiding makeQImage(transpose=True)
- ComboBox will raise error when adding multiple items of the same name - ComboBox will raise error when adding multiple items of the same name
- ArrowItem.setStyle now updates style options rather than replacing them - ArrowItem.setStyle now updates style options rather than replacing them
- Renamed GraphicsView signals to avoid collision with ViewBox signals that
are wrapped in PlotWidget: sigRangeChanged => sigDeviceRangeChanged and
sigTransformChanged => sigDeviceTransformChanged.
New Features: New Features:
- Added ViewBox.setLimits() method - Added ViewBox.setLimits() method

View File

@ -227,18 +227,11 @@ class Flowchart(Node):
def nodeClosed(self, node): def nodeClosed(self, node):
del self._nodes[node.name()] del self._nodes[node.name()]
self.widget().removeNode(node) self.widget().removeNode(node)
try: for signal in ['sigClosed', 'sigRenamed', 'sigOutputChanged']:
node.sigClosed.disconnect(self.nodeClosed) try:
except TypeError: getattr(node, signal).disconnect(self.nodeClosed)
pass except (TypeError, RuntimeError):
try: pass
node.sigRenamed.disconnect(self.nodeRenamed)
except TypeError:
pass
try:
node.sigOutputChanged.disconnect(self.nodeOutputChanged)
except TypeError:
pass
self.sigChartChanged.emit(self, 'remove', node) self.sigChartChanged.emit(self, 'remove', node)
def nodeRenamed(self, node, oldName): def nodeRenamed(self, node, oldName):
@ -769,7 +762,7 @@ class FlowchartCtrlWidget(QtGui.QWidget):
#self.disconnect(item.bypassBtn, QtCore.SIGNAL('clicked()'), self.bypassClicked) #self.disconnect(item.bypassBtn, QtCore.SIGNAL('clicked()'), self.bypassClicked)
try: try:
item.bypassBtn.clicked.disconnect(self.bypassClicked) item.bypassBtn.clicked.disconnect(self.bypassClicked)
except TypeError: except (TypeError, RuntimeError):
pass pass
self.ui.ctrlList.removeTopLevelItem(item) self.ui.ctrlList.removeTopLevelItem(item)

View File

@ -28,7 +28,7 @@ class FillBetweenItem(QtGui.QGraphicsPathItem):
for c in self.curves: for c in self.curves:
try: try:
c.sigPlotChanged.disconnect(self.curveChanged) c.sigPlotChanged.disconnect(self.curveChanged)
except TypeError: except (TypeError, RuntimeError):
pass pass
curves = [curve1, curve2] curves = [curve1, curve2]

View File

@ -479,24 +479,29 @@ class GraphicsItem(object):
## disconnect from previous view ## disconnect from previous view
if oldView is not None: if oldView is not None:
#print "disconnect:", self, oldView for signal, slot in [('sigRangeChanged', self.viewRangeChanged),
try: ('sigDeviceRangeChanged', self.viewRangeChanged),
oldView.sigRangeChanged.disconnect(self.viewRangeChanged) ('sigTransformChanged', self.viewTransformChanged),
except TypeError: ('sigDeviceTransformChanged', self.viewTransformChanged)]:
pass try:
getattr(oldView, signal).disconnect(slot)
try: except (TypeError, AttributeError, RuntimeError):
oldView.sigTransformChanged.disconnect(self.viewTransformChanged) # TypeError and RuntimeError are from pyqt and pyside, respectively
except TypeError: pass
pass
self._connectedView = None self._connectedView = None
## connect to new view ## connect to new view
if view is not None: if view is not None:
#print "connect:", self, view #print "connect:", self, view
view.sigRangeChanged.connect(self.viewRangeChanged) if hasattr(view, 'sigDeviceRangeChanged'):
view.sigTransformChanged.connect(self.viewTransformChanged) # connect signals from GraphicsView
view.sigDeviceRangeChanged.connect(self.viewRangeChanged)
view.sigDeviceTransformChanged.connect(self.viewTransformChanged)
else:
# connect signals from ViewBox
view.sigRangeChanged.connect(self.viewRangeChanged)
view.sigTransformChanged.connect(self.viewTransformChanged)
self._connectedView = weakref.ref(view) self._connectedView = weakref.ref(view)
self.viewRangeChanged() self.viewRangeChanged()
self.viewTransformChanged() self.viewTransformChanged()

View File

@ -881,7 +881,7 @@ class ViewBox(GraphicsWidget):
try: try:
getattr(oldLink, signal).disconnect(slot) getattr(oldLink, signal).disconnect(slot)
oldLink.sigResized.disconnect(slot) oldLink.sigResized.disconnect(slot)
except TypeError: except (TypeError, RuntimeError):
## This can occur if the view has been deleted already ## This can occur if the view has been deleted already
pass pass

View File

@ -19,11 +19,14 @@ def mkQApp():
class GraphicsWindow(GraphicsLayoutWidget): class GraphicsWindow(GraphicsLayoutWidget):
"""
Convenience subclass of :class:`GraphicsLayoutWidget
<pyqtgraph.GraphicsLayoutWidget>`. This class is intended for use from
the interactive python prompt.
"""
def __init__(self, title=None, size=(800,600), **kargs): def __init__(self, title=None, size=(800,600), **kargs):
mkQApp() mkQApp()
#self.win = QtGui.QMainWindow()
GraphicsLayoutWidget.__init__(self, **kargs) GraphicsLayoutWidget.__init__(self, **kargs)
#self.win.setCentralWidget(self)
self.resize(*size) self.resize(*size)
if title is not None: if title is not None:
self.setWindowTitle(title) self.setWindowTitle(title)

View File

@ -516,7 +516,7 @@ class Parameter(QtCore.QObject):
self.sigChildRemoved.emit(self, child) self.sigChildRemoved.emit(self, child)
try: try:
child.sigTreeStateChanged.disconnect(self.treeStateChanged) child.sigTreeStateChanged.disconnect(self.treeStateChanged)
except TypeError: ## already disconnected except (TypeError, RuntimeError): ## already disconnected
pass pass
def clearChildren(self): def clearChildren(self):

View File

@ -4,9 +4,27 @@ from .GraphicsView import GraphicsView
__all__ = ['GraphicsLayoutWidget'] __all__ = ['GraphicsLayoutWidget']
class GraphicsLayoutWidget(GraphicsView): class GraphicsLayoutWidget(GraphicsView):
"""
Convenience class consisting of a :class:`GraphicsView
<pyqtgraph.GraphicsView>` with a single :class:`GraphicsLayout
<pyqtgraph.GraphicsLayout>` as its central item.
This class wraps several methods from its internal GraphicsLayout:
:func:`nextRow <pyqtgraph.GraphicsLayout.nextRow>`
:func:`nextColumn <pyqtgraph.GraphicsLayout.nextColumn>`
:func:`addPlot <pyqtgraph.GraphicsLayout.addPlot>`
:func:`addViewBox <pyqtgraph.GraphicsLayout.addViewBox>`
:func:`addItem <pyqtgraph.GraphicsLayout.addItem>`
:func:`getItem <pyqtgraph.GraphicsLayout.getItem>`
:func:`addLabel <pyqtgraph.GraphicsLayout.addLabel>`
:func:`addLayout <pyqtgraph.GraphicsLayout.addLayout>`
:func:`removeItem <pyqtgraph.GraphicsLayout.removeItem>`
:func:`itemIndex <pyqtgraph.GraphicsLayout.itemIndex>`
:func:`clear <pyqtgraph.GraphicsLayout.clear>`
"""
def __init__(self, parent=None, **kargs): def __init__(self, parent=None, **kargs):
GraphicsView.__init__(self, parent) GraphicsView.__init__(self, parent)
self.ci = GraphicsLayout(**kargs) self.ci = GraphicsLayout(**kargs)
for n in ['nextRow', 'nextCol', 'nextColumn', 'addPlot', 'addViewBox', 'addItem', 'getItem', 'addLabel', 'addLayout', 'addLabel', 'addViewBox', 'removeItem', 'itemIndex', 'clear']: for n in ['nextRow', 'nextCol', 'nextColumn', 'addPlot', 'addViewBox', 'addItem', 'getItem', 'addLayout', 'addLabel', 'removeItem', 'itemIndex', 'clear']:
setattr(self, n, getattr(self.ci, n)) setattr(self, n, getattr(self.ci, n))
self.setCentralItem(self.ci) self.setCentralItem(self.ci)

View File

@ -40,8 +40,8 @@ class GraphicsView(QtGui.QGraphicsView):
The view can be panned using the middle mouse button and scaled using the right mouse button if The view can be panned using the middle mouse button and scaled using the right mouse button if
enabled via enableMouse() (but ordinarily, we use ViewBox for this functionality).""" enabled via enableMouse() (but ordinarily, we use ViewBox for this functionality)."""
sigRangeChanged = QtCore.Signal(object, object) sigDeviceRangeChanged = QtCore.Signal(object, object)
sigTransformChanged = QtCore.Signal(object) sigDeviceTransformChanged = QtCore.Signal(object)
sigMouseReleased = QtCore.Signal(object) sigMouseReleased = QtCore.Signal(object)
sigSceneMouseMoved = QtCore.Signal(object) sigSceneMouseMoved = QtCore.Signal(object)
#sigRegionChanged = QtCore.Signal(object) #sigRegionChanged = QtCore.Signal(object)
@ -219,8 +219,8 @@ class GraphicsView(QtGui.QGraphicsView):
else: else:
self.fitInView(self.range, QtCore.Qt.IgnoreAspectRatio) self.fitInView(self.range, QtCore.Qt.IgnoreAspectRatio)
self.sigRangeChanged.emit(self, self.range) self.sigDeviceRangeChanged.emit(self, self.range)
self.sigTransformChanged.emit(self) self.sigDeviceTransformChanged.emit(self)
if propagate: if propagate:
for v in self.lockedViewports: for v in self.lockedViewports:
@ -287,7 +287,7 @@ class GraphicsView(QtGui.QGraphicsView):
image.setPxMode(True) image.setPxMode(True)
try: try:
self.sigScaleChanged.disconnect(image.setScaledMode) self.sigScaleChanged.disconnect(image.setScaledMode)
except TypeError: except (TypeError, RuntimeError):
pass pass
tl = image.sceneBoundingRect().topLeft() tl = image.sceneBoundingRect().topLeft()
w = self.size().width() * pxSize[0] w = self.size().width() * pxSize[0]
@ -368,14 +368,14 @@ class GraphicsView(QtGui.QGraphicsView):
delta = Point(np.clip(delta[0], -50, 50), np.clip(-delta[1], -50, 50)) delta = Point(np.clip(delta[0], -50, 50), np.clip(-delta[1], -50, 50))
scale = 1.01 ** delta scale = 1.01 ** delta
self.scale(scale[0], scale[1], center=self.mapToScene(self.mousePressPos)) self.scale(scale[0], scale[1], center=self.mapToScene(self.mousePressPos))
self.sigRangeChanged.emit(self, self.range) self.sigDeviceRangeChanged.emit(self, self.range)
elif ev.buttons() in [QtCore.Qt.MidButton, QtCore.Qt.LeftButton]: ## Allow panning by left or mid button. elif ev.buttons() in [QtCore.Qt.MidButton, QtCore.Qt.LeftButton]: ## Allow panning by left or mid button.
px = self.pixelSize() px = self.pixelSize()
tr = -delta * px tr = -delta * px
self.translate(tr[0], tr[1]) self.translate(tr[0], tr[1])
self.sigRangeChanged.emit(self, self.range) self.sigDeviceRangeChanged.emit(self, self.range)
def pixelSize(self): def pixelSize(self):
"""Return vector with the length and width of one view pixel in scene coordinates""" """Return vector with the length and width of one view pixel in scene coordinates"""

View File

@ -12,7 +12,9 @@ from ..graphicsItems.PlotItem import *
__all__ = ['PlotWidget'] __all__ = ['PlotWidget']
class PlotWidget(GraphicsView): class PlotWidget(GraphicsView):
#sigRangeChanged = QtCore.Signal(object, object) ## already defined in GraphicsView # signals wrapped from PlotItem / ViewBox
sigRangeChanged = QtCore.Signal(object, object)
sigTransformChanged = QtCore.Signal(object)
""" """
:class:`GraphicsView <pyqtgraph.GraphicsView>` widget with a single :class:`GraphicsView <pyqtgraph.GraphicsView>` widget with a single