Fixed PySide issues by removing itemChange methods from GraphicsWidget and ViewBox;

Workaround is for ViewBox to see whether its scene has changed every time it paints.

Fixes: 12
This commit is contained in:
Luke Campagnola 2013-11-16 20:23:41 -05:00
parent 25d666a1da
commit 8d7ab108fd
6 changed files with 89 additions and 54 deletions

View File

@ -13,7 +13,6 @@ import initExample ## Add path to library (just for examples; you do not need th
from pyqtgraph.Qt import QtGui, QtCore, USE_PYSIDE
import numpy as np
import pyqtgraph as pg
from pyqtgraph import RawImageWidget
import scipy.ndimage as ndi
import pyqtgraph.ptime as ptime

View File

@ -22,9 +22,6 @@
<property name="text">
<string>RawImageWidget</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
@ -32,6 +29,9 @@
<property name="text">
<string>GraphicsView + ImageItem</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
@ -265,7 +265,7 @@
<customwidget>
<class>RawImageWidget</class>
<extends>QWidget</extends>
<header>pyqtgraph</header>
<header>pyqtgraph.widgets.RawImageWidget</header>
<container>1</container>
</customwidget>
<customwidget>

View File

@ -2,8 +2,8 @@
# Form implementation generated from reading ui file './VideoTemplate.ui'
#
# Created: Tue Jul 9 23:38:17 2013
# by: PyQt4 UI code generator 4.9.3
# Created: Sat Nov 16 20:07:09 2013
# by: PyQt4 UI code generator 4.10
#
# WARNING! All changes made in this file will be lost!
@ -12,7 +12,16 @@ from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
@ -25,10 +34,10 @@ class Ui_MainWindow(object):
self.gridLayout = QtGui.QGridLayout()
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.rawRadio = QtGui.QRadioButton(self.centralwidget)
self.rawRadio.setChecked(True)
self.rawRadio.setObjectName(_fromUtf8("rawRadio"))
self.gridLayout.addWidget(self.rawRadio, 3, 0, 1, 1)
self.gfxRadio = QtGui.QRadioButton(self.centralwidget)
self.gfxRadio.setChecked(True)
self.gfxRadio.setObjectName(_fromUtf8("gfxRadio"))
self.gridLayout.addWidget(self.gfxRadio, 2, 0, 1, 1)
self.stack = QtGui.QStackedWidget(self.centralwidget)
@ -158,23 +167,23 @@ class Ui_MainWindow(object):
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
self.rawRadio.setText(QtGui.QApplication.translate("MainWindow", "RawImageWidget", None, QtGui.QApplication.UnicodeUTF8))
self.gfxRadio.setText(QtGui.QApplication.translate("MainWindow", "GraphicsView + ImageItem", None, QtGui.QApplication.UnicodeUTF8))
self.rawGLRadio.setText(QtGui.QApplication.translate("MainWindow", "RawGLImageWidget", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("MainWindow", "Data type", None, QtGui.QApplication.UnicodeUTF8))
self.dtypeCombo.setItemText(0, QtGui.QApplication.translate("MainWindow", "uint8", None, QtGui.QApplication.UnicodeUTF8))
self.dtypeCombo.setItemText(1, QtGui.QApplication.translate("MainWindow", "uint16", None, QtGui.QApplication.UnicodeUTF8))
self.dtypeCombo.setItemText(2, QtGui.QApplication.translate("MainWindow", "float", None, QtGui.QApplication.UnicodeUTF8))
self.scaleCheck.setText(QtGui.QApplication.translate("MainWindow", "Scale Data", None, QtGui.QApplication.UnicodeUTF8))
self.rgbLevelsCheck.setText(QtGui.QApplication.translate("MainWindow", "RGB", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("MainWindow", "<--->", None, QtGui.QApplication.UnicodeUTF8))
self.label_3.setText(QtGui.QApplication.translate("MainWindow", "<--->", None, QtGui.QApplication.UnicodeUTF8))
self.label_4.setText(QtGui.QApplication.translate("MainWindow", "<--->", None, QtGui.QApplication.UnicodeUTF8))
self.lutCheck.setText(QtGui.QApplication.translate("MainWindow", "Use Lookup Table", None, QtGui.QApplication.UnicodeUTF8))
self.alphaCheck.setText(QtGui.QApplication.translate("MainWindow", "alpha", None, QtGui.QApplication.UnicodeUTF8))
self.fpsLabel.setText(QtGui.QApplication.translate("MainWindow", "FPS", None, QtGui.QApplication.UnicodeUTF8))
self.rgbCheck.setText(QtGui.QApplication.translate("MainWindow", "RGB", None, QtGui.QApplication.UnicodeUTF8))
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
self.rawRadio.setText(_translate("MainWindow", "RawImageWidget", None))
self.gfxRadio.setText(_translate("MainWindow", "GraphicsView + ImageItem", None))
self.rawGLRadio.setText(_translate("MainWindow", "RawGLImageWidget", None))
self.label.setText(_translate("MainWindow", "Data type", None))
self.dtypeCombo.setItemText(0, _translate("MainWindow", "uint8", None))
self.dtypeCombo.setItemText(1, _translate("MainWindow", "uint16", None))
self.dtypeCombo.setItemText(2, _translate("MainWindow", "float", None))
self.scaleCheck.setText(_translate("MainWindow", "Scale Data", None))
self.rgbLevelsCheck.setText(_translate("MainWindow", "RGB", None))
self.label_2.setText(_translate("MainWindow", "<--->", None))
self.label_3.setText(_translate("MainWindow", "<--->", None))
self.label_4.setText(_translate("MainWindow", "<--->", None))
self.lutCheck.setText(_translate("MainWindow", "Use Lookup Table", None))
self.alphaCheck.setText(_translate("MainWindow", "alpha", None))
self.fpsLabel.setText(_translate("MainWindow", "FPS", None))
self.rgbCheck.setText(_translate("MainWindow", "RGB", None))
from pyqtgraph.widgets.RawImageWidget import RawImageGLWidget
from pyqtgraph import GradientWidget, SpinBox, GraphicsView, RawImageWidget
from pyqtgraph.widgets.RawImageWidget import RawImageGLWidget, RawImageWidget
from pyqtgraph import GradientWidget, SpinBox, GraphicsView

View File

@ -2,8 +2,8 @@
# Form implementation generated from reading ui file './VideoTemplate.ui'
#
# Created: Tue Jul 9 23:38:19 2013
# by: pyside-uic 0.2.13 running on PySide 1.1.2
# Created: Sat Nov 16 20:07:10 2013
# by: pyside-uic 0.2.14 running on PySide 1.1.2
#
# WARNING! All changes made in this file will be lost!
@ -20,10 +20,10 @@ class Ui_MainWindow(object):
self.gridLayout = QtGui.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.rawRadio = QtGui.QRadioButton(self.centralwidget)
self.rawRadio.setChecked(True)
self.rawRadio.setObjectName("rawRadio")
self.gridLayout.addWidget(self.rawRadio, 3, 0, 1, 1)
self.gfxRadio = QtGui.QRadioButton(self.centralwidget)
self.gfxRadio.setChecked(True)
self.gfxRadio.setObjectName("gfxRadio")
self.gridLayout.addWidget(self.gfxRadio, 2, 0, 1, 1)
self.stack = QtGui.QStackedWidget(self.centralwidget)
@ -171,5 +171,5 @@ class Ui_MainWindow(object):
self.fpsLabel.setText(QtGui.QApplication.translate("MainWindow", "FPS", None, QtGui.QApplication.UnicodeUTF8))
self.rgbCheck.setText(QtGui.QApplication.translate("MainWindow", "RGB", None, QtGui.QApplication.UnicodeUTF8))
from pyqtgraph.widgets.RawImageWidget import RawImageGLWidget
from pyqtgraph import GradientWidget, SpinBox, GraphicsView, RawImageWidget
from pyqtgraph.widgets.RawImageWidget import RawImageGLWidget, RawImageWidget
from pyqtgraph import GradientWidget, SpinBox, GraphicsView

View File

@ -20,16 +20,17 @@ class GraphicsWidget(GraphicsItem, QtGui.QGraphicsWidget):
## done by GraphicsItem init
#GraphicsScene.registerObject(self) ## workaround for pyqt bug in graphicsscene.items()
## Removed because this causes segmentation faults. Don't know why.
# def itemChange(self, change, value):
# ret = QtGui.QGraphicsWidget.itemChange(self, change, value) ## segv occurs here
# if change in [self.ItemParentHasChanged, self.ItemSceneHasChanged]:
# self._updateView()
# return ret
# Removed due to https://bugreports.qt-project.org/browse/PYSIDE-86
#def itemChange(self, change, value):
## BEWARE: Calling QGraphicsWidget.itemChange can lead to crashing!
##ret = QtGui.QGraphicsWidget.itemChange(self, change, value) ## segv occurs here
## The default behavior is just to return the value argument, so we'll do that
## without calling the original method.
#ret = value
#if change in [self.ItemParentHasChanged, self.ItemSceneHasChanged]:
#self._updateView()
#return ret
#def getMenu(self):
#pass
def setFixedHeight(self, h):
self.setMaximumHeight(h)
self.setMinimumHeight(h)

View File

@ -93,6 +93,8 @@ class ViewBox(GraphicsWidget):
#self.showGrid = showGrid
self._matrixNeedsUpdate = True ## indicates that range has changed, but matrix update was deferred
self._autoRangeNeedsUpdate = True ## indicates auto-range needs to be recomputed.
self._lastScene = None ## stores reference to the last known scene this view was a part of.
self.state = {
@ -200,18 +202,40 @@ class ViewBox(GraphicsWidget):
def implements(self, interface):
return interface == 'ViewBox'
def itemChange(self, change, value):
# Note: Calling QWidget.itemChange causes segv in python 3 + PyQt
ret = QtGui.QGraphicsItem.itemChange(self, change, value)
if change == self.ItemSceneChange:
scene = self.scene()
if scene is not None:
scene.sigPrepareForPaint.disconnect(self.prepareForPaint)
elif change == self.ItemSceneHasChanged:
scene = self.scene()
if scene is not None:
scene.sigPrepareForPaint.connect(self.prepareForPaint)
return ret
# removed due to https://bugreports.qt-project.org/browse/PYSIDE-86
#def itemChange(self, change, value):
## Note: Calling QWidget.itemChange causes segv in python 3 + PyQt
##ret = QtGui.QGraphicsItem.itemChange(self, change, value)
#ret = GraphicsWidget.itemChange(self, change, value)
#if change == self.ItemSceneChange:
#scene = self.scene()
#if scene is not None and hasattr(scene, 'sigPrepareForPaint'):
#scene.sigPrepareForPaint.disconnect(self.prepareForPaint)
#elif change == self.ItemSceneHasChanged:
#scene = self.scene()
#if scene is not None and hasattr(scene, 'sigPrepareForPaint'):
#scene.sigPrepareForPaint.connect(self.prepareForPaint)
#return ret
def checkSceneChange(self):
# ViewBox needs to receive sigPrepareForPaint from its scene before
# being painted. However, we have no way of being informed when the
# scene has changed in order to make this connection. The usual way
# to do this is via itemChange(), but bugs prevent this approach
# (see above). Instead, we simply check at every paint to see whether
# (the scene has changed.
scene = self.scene()
if scene == self._lastScene:
return
if self._lastScene is not None and hasattr(self.lastScene, 'sigPrepareForPaint'):
self._lastScene.sigPrepareForPaint.disconnect(self.prepareForPaint)
if scene is not None and hasattr(scene, 'sigPrepareForPaint'):
scene.sigPrepareForPaint.connect(self.prepareForPaint)
self.prepareForPaint()
self._lastScene = scene
def prepareForPaint(self):
#autoRangeEnabled = (self.state['autoRange'][0] is not False) or (self.state['autoRange'][1] is not False)
@ -1446,6 +1470,8 @@ class ViewBox(GraphicsWidget):
self._matrixNeedsUpdate = False
def paint(self, p, opt, widget):
self.checkSceneChange()
if self.border is not None:
bounds = self.shape()
p.setPen(self.border)