Moved emits after all method state updates since PySide2 immediately executes signals.
Pull request #907 addressed a specific case where a signal was emitted before a state update. If an application's slot then calls back into the instance, the instance was in an inconsistent state. This commit audits and fixes similar issues throughout the pyqtgraph library. This commit fixes several latent issues: * SignalProxy: flush -> sigDelayed -> signalReceived would have incorrectly resulted in timer.stop(). * ViewBox: resizeEvent -> sigStateChange -> background state * ViewBox: setRange -> sigStateChange -> autoranging not updated correctly * ViewBox: updateMatrix -> sigTransformChanged -> any _matrixNeedsUpdate = True -> ignored * Parameter: Child may have missed state tree messages on insert or received extra on remove * GraphicsView: updateMatrix -> sigDeviceRangeChanged/sigDeviceTransformChange -> before propagated to locked viewports.
This commit is contained in:
parent
eb90616ae2
commit
c52382c3b9
@ -67,11 +67,11 @@ class SignalProxy(QtCore.QObject):
|
||||
"""If there is a signal queued up, send it now."""
|
||||
if self.args is None or self.block:
|
||||
return False
|
||||
#self.emit(self.signal, *self.args)
|
||||
self.sigDelayed.emit(self.args)
|
||||
self.args = None
|
||||
args, self.args = self.args, None
|
||||
self.timer.stop()
|
||||
self.lastFlushTime = time()
|
||||
#self.emit(self.signal, *self.args)
|
||||
self.sigDelayed.emit(args)
|
||||
return True
|
||||
|
||||
def disconnect(self):
|
||||
|
@ -346,9 +346,9 @@ class DockLabel(VerticalLabel):
|
||||
ev.accept()
|
||||
|
||||
def mouseReleaseEvent(self, ev):
|
||||
ev.accept()
|
||||
if not self.startedDrag:
|
||||
self.sigClicked.emit(self, ev)
|
||||
ev.accept()
|
||||
|
||||
def mouseDoubleClickEvent(self, ev):
|
||||
if ev.button() == QtCore.Qt.LeftButton:
|
||||
|
@ -503,8 +503,8 @@ class Flowchart(Node):
|
||||
finally:
|
||||
self.blockSignals(False)
|
||||
|
||||
self.sigChartLoaded.emit()
|
||||
self.outputChanged()
|
||||
self.sigChartLoaded.emit()
|
||||
self.sigStateChanged.emit()
|
||||
|
||||
def loadFile(self, fileName=None, startDir=None):
|
||||
|
@ -205,8 +205,8 @@ class HistogramLUTItem(GraphicsWidget):
|
||||
def regionChanging(self):
|
||||
if self.imageItem() is not None:
|
||||
self.imageItem().setLevels(self.getLevels())
|
||||
self.sigLevelsChanged.emit(self)
|
||||
self.update()
|
||||
self.sigLevelsChanged.emit(self)
|
||||
|
||||
def imageChanged(self, autoLevel=False, autoRange=False):
|
||||
if self.imageItem() is None:
|
||||
|
@ -711,10 +711,10 @@ class ROI(GraphicsObject):
|
||||
|
||||
if hover:
|
||||
self.setMouseHover(True)
|
||||
self.sigHoverEvent.emit(self)
|
||||
ev.acceptClicks(QtCore.Qt.LeftButton) ## If the ROI is hilighted, we should accept all clicks to avoid confusion.
|
||||
ev.acceptClicks(QtCore.Qt.RightButton)
|
||||
ev.acceptClicks(QtCore.Qt.MidButton)
|
||||
self.sigHoverEvent.emit(self)
|
||||
else:
|
||||
self.setMouseHover(False)
|
||||
|
||||
|
@ -834,8 +834,8 @@ class ScatterPlotItem(GraphicsObject):
|
||||
pts = self.pointsAt(ev.pos())
|
||||
if len(pts) > 0:
|
||||
self.ptsClicked = pts
|
||||
self.sigClicked.emit(self, self.ptsClicked)
|
||||
ev.accept()
|
||||
self.sigClicked.emit(self, self.ptsClicked)
|
||||
else:
|
||||
#print "no spots"
|
||||
ev.ignore()
|
||||
|
@ -427,8 +427,8 @@ class ViewBox(GraphicsWidget):
|
||||
self.updateAutoRange()
|
||||
self.updateViewRange()
|
||||
self._matrixNeedsUpdate = True
|
||||
self.sigStateChanged.emit(self)
|
||||
self.background.setRect(self.rect())
|
||||
self.sigStateChanged.emit(self)
|
||||
self.sigResized.emit(self)
|
||||
|
||||
def viewRange(self):
|
||||
@ -561,8 +561,6 @@ class ViewBox(GraphicsWidget):
|
||||
|
||||
# If nothing has changed, we are done.
|
||||
if any(changed):
|
||||
self.sigStateChanged.emit(self)
|
||||
|
||||
# Update target rect for debugging
|
||||
if self.target.isVisible():
|
||||
self.target.setRect(self.mapRectFromItem(self.childGroup, self.targetRect()))
|
||||
@ -574,6 +572,8 @@ class ViewBox(GraphicsWidget):
|
||||
elif changed[1] and self.state['autoVisibleOnly'][0] and (self.state['autoRange'][1] is not False):
|
||||
self._autoRangeNeedsUpdate = True
|
||||
|
||||
self.sigStateChanged.emit(self)
|
||||
|
||||
def setYRange(self, min, max, padding=None, update=True):
|
||||
"""
|
||||
Set the visible Y range of the view to [*min*, *max*].
|
||||
@ -1156,8 +1156,8 @@ class ViewBox(GraphicsWidget):
|
||||
|
||||
self._resetTarget()
|
||||
self.scaleBy(s, center)
|
||||
self.sigRangeChangedManually.emit(mask)
|
||||
ev.accept()
|
||||
self.sigRangeChangedManually.emit(mask)
|
||||
|
||||
def mouseClickEvent(self, ev):
|
||||
if ev.button() == QtCore.Qt.RightButton and self.menuEnabled():
|
||||
@ -1498,12 +1498,6 @@ class ViewBox(GraphicsWidget):
|
||||
|
||||
if any(changed):
|
||||
self._matrixNeedsUpdate = True
|
||||
# emit range change signals
|
||||
if changed[0]:
|
||||
self.sigXRangeChanged.emit(self, tuple(self.state['viewRange'][0]))
|
||||
if changed[1]:
|
||||
self.sigYRangeChanged.emit(self, tuple(self.state['viewRange'][1]))
|
||||
self.sigRangeChanged.emit(self, self.state['viewRange'])
|
||||
self.update()
|
||||
|
||||
# Inform linked views that the range has changed
|
||||
@ -1514,6 +1508,13 @@ class ViewBox(GraphicsWidget):
|
||||
if link is not None:
|
||||
link.linkedViewChanged(self, ax)
|
||||
|
||||
# emit range change signals
|
||||
if changed[0]:
|
||||
self.sigXRangeChanged.emit(self, tuple(self.state['viewRange'][0]))
|
||||
if changed[1]:
|
||||
self.sigYRangeChanged.emit(self, tuple(self.state['viewRange'][1]))
|
||||
self.sigRangeChanged.emit(self, self.state['viewRange'])
|
||||
|
||||
def updateMatrix(self, changed=None):
|
||||
if not self._matrixNeedsUpdate:
|
||||
return
|
||||
@ -1541,9 +1542,9 @@ class ViewBox(GraphicsWidget):
|
||||
m.translate(-st[0], -st[1])
|
||||
|
||||
self.childGroup.setTransform(m)
|
||||
self._matrixNeedsUpdate = False
|
||||
|
||||
self.sigTransformChanged.emit(self) ## segfaults here: 1
|
||||
self._matrixNeedsUpdate = False
|
||||
|
||||
def paint(self, p, opt, widget):
|
||||
self.checkSceneChange()
|
||||
|
@ -559,8 +559,8 @@ class Parameter(QtCore.QObject):
|
||||
self.childs.insert(pos, child)
|
||||
|
||||
child.parentChanged(self)
|
||||
self.sigChildAdded.emit(self, child, pos)
|
||||
child.sigTreeStateChanged.connect(self.treeStateChanged)
|
||||
self.sigChildAdded.emit(self, child, pos)
|
||||
return child
|
||||
|
||||
def removeChild(self, child):
|
||||
@ -571,11 +571,11 @@ class Parameter(QtCore.QObject):
|
||||
del self.names[name]
|
||||
self.childs.pop(self.childs.index(child))
|
||||
child.parentChanged(None)
|
||||
self.sigChildRemoved.emit(self, child)
|
||||
try:
|
||||
child.sigTreeStateChanged.disconnect(self.treeStateChanged)
|
||||
except (TypeError, RuntimeError): ## already disconnected
|
||||
pass
|
||||
self.sigChildRemoved.emit(self, child)
|
||||
|
||||
def clearChildren(self):
|
||||
"""Remove all child parameters."""
|
||||
|
@ -50,11 +50,11 @@ class ColorButton(QtGui.QPushButton):
|
||||
def setColor(self, color, finished=True):
|
||||
"""Sets the button's color and emits both sigColorChanged and sigColorChanging."""
|
||||
self._color = functions.mkColor(color)
|
||||
self.update()
|
||||
if finished:
|
||||
self.sigColorChanged.emit(self)
|
||||
else:
|
||||
self.sigColorChanging.emit(self)
|
||||
self.update()
|
||||
|
||||
def selectColor(self):
|
||||
self.origColor = self.color()
|
||||
|
@ -227,13 +227,13 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
else:
|
||||
self.fitInView(self.range, QtCore.Qt.IgnoreAspectRatio)
|
||||
|
||||
self.sigDeviceRangeChanged.emit(self, self.range)
|
||||
self.sigDeviceTransformChanged.emit(self)
|
||||
|
||||
if propagate:
|
||||
for v in self.lockedViewports:
|
||||
v.setXRange(self.range, padding=0)
|
||||
|
||||
self.sigDeviceRangeChanged.emit(self, self.range)
|
||||
self.sigDeviceTransformChanged.emit(self)
|
||||
|
||||
def viewRect(self):
|
||||
"""Return the boundaries of the view in scene coordinates"""
|
||||
## easier to just return self.range ?
|
||||
@ -262,7 +262,6 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
h = self.range.height() / scale[1]
|
||||
self.range = QtCore.QRectF(center.x() - (center.x()-self.range.left()) / scale[0], center.y() - (center.y()-self.range.top()) /scale[1], w, h)
|
||||
|
||||
|
||||
self.updateMatrix()
|
||||
self.sigScaleChanged.emit(self)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user