Bugfixes:
- GraphicsView.render now correctly invokes GraphicsScene.prepareForPaint - Fixed RemoteGraphicsView renderer to use new PyQt QImage API. - multiprocess.Process now pipes stdout/err directly to console when in debugging mode
This commit is contained in:
parent
ea8079334f
commit
31928e70a5
@ -13,7 +13,8 @@ from pyqtgraph.widgets.RemoteGraphicsView import RemoteGraphicsView
|
|||||||
app = pg.mkQApp()
|
app = pg.mkQApp()
|
||||||
|
|
||||||
## Create the widget
|
## Create the widget
|
||||||
v = RemoteGraphicsView(debug=False)
|
v = RemoteGraphicsView(debug=False) # setting debug=True causes both processes to print information
|
||||||
|
# about interprocess communication
|
||||||
v.show()
|
v.show()
|
||||||
v.setWindowTitle('pyqtgraph example: RemoteGraphicsView')
|
v.setWindowTitle('pyqtgraph example: RemoteGraphicsView')
|
||||||
|
|
||||||
|
@ -311,13 +311,15 @@ def image(*args, **kargs):
|
|||||||
return w
|
return w
|
||||||
show = image ## for backward compatibility
|
show = image ## for backward compatibility
|
||||||
|
|
||||||
def dbg():
|
def dbg(*args, **kwds):
|
||||||
"""
|
"""
|
||||||
Create a console window and begin watching for exceptions.
|
Create a console window and begin watching for exceptions.
|
||||||
|
|
||||||
|
All arguments are passed to :func:`ConsoleWidget.__init__() <pyqtgraph.console.ConsoleWidget.__init__>`.
|
||||||
"""
|
"""
|
||||||
mkQApp()
|
mkQApp()
|
||||||
from . import console
|
from . import console
|
||||||
c = console.ConsoleWidget()
|
c = console.ConsoleWidget(*args, **kwds)
|
||||||
c.catchAllExceptions()
|
c.catchAllExceptions()
|
||||||
c.show()
|
c.show()
|
||||||
global consoles
|
global consoles
|
||||||
|
@ -20,10 +20,8 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
if opts.pop('pyside', False):
|
if opts.pop('pyside', False):
|
||||||
import PySide
|
import PySide
|
||||||
#import pyqtgraph
|
|
||||||
#import pyqtgraph.multiprocess.processes
|
|
||||||
targetStr = opts.pop('targetStr')
|
targetStr = opts.pop('targetStr')
|
||||||
target = pickle.loads(targetStr) ## unpickling the target should import everything we need
|
target = pickle.loads(targetStr) ## unpickling the target should import everything we need
|
||||||
#target(name, port, authkey, ppid)
|
|
||||||
target(**opts) ## Send all other options to the target function
|
target(**opts) ## Send all other options to the target function
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
@ -48,9 +48,10 @@ class Process(RemoteEventHandler):
|
|||||||
it must be picklable (bound methods are not).
|
it must be picklable (bound methods are not).
|
||||||
copySysPath If True, copy the contents of sys.path to the remote process
|
copySysPath If True, copy the contents of sys.path to the remote process
|
||||||
debug If True, print detailed information about communication
|
debug If True, print detailed information about communication
|
||||||
with the child process.
|
with the child process. Note that this option may cause
|
||||||
|
strange behavior on some systems due to a python bug:
|
||||||
|
http://bugs.python.org/issue3905
|
||||||
============ =============================================================
|
============ =============================================================
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if target is None:
|
if target is None:
|
||||||
target = startEventLoop
|
target = startEventLoop
|
||||||
@ -82,7 +83,13 @@ class Process(RemoteEventHandler):
|
|||||||
|
|
||||||
## note: we need all three streams to have their own PIPE due to this bug:
|
## note: we need all three streams to have their own PIPE due to this bug:
|
||||||
## http://bugs.python.org/issue3905
|
## http://bugs.python.org/issue3905
|
||||||
self.proc = subprocess.Popen((executable, bootstrap), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
if debug is True: # when debugging, we need to keep the usual stdout
|
||||||
|
stdout = sys.stdout
|
||||||
|
stderr = sys.stderr
|
||||||
|
else:
|
||||||
|
stdout = subprocess.PIPE
|
||||||
|
stderr = subprocess.PIPE
|
||||||
|
self.proc = subprocess.Popen((executable, bootstrap), stdin=subprocess.PIPE, stdout=stdout, stderr=stderr)
|
||||||
|
|
||||||
targetStr = pickle.dumps(target) ## double-pickle target so that child has a chance to
|
targetStr = pickle.dumps(target) ## double-pickle target so that child has a chance to
|
||||||
## set its sys.path properly before unpickling the target
|
## set its sys.path properly before unpickling the target
|
||||||
|
@ -147,6 +147,11 @@ class GraphicsView(QtGui.QGraphicsView):
|
|||||||
#print "GV: paint", ev.rect()
|
#print "GV: paint", ev.rect()
|
||||||
return QtGui.QGraphicsView.paintEvent(self, ev)
|
return QtGui.QGraphicsView.paintEvent(self, ev)
|
||||||
|
|
||||||
|
def render(self, *args, **kwds):
|
||||||
|
self.scene().prepareForPaint()
|
||||||
|
return QtGui.QGraphicsView.render(self, *args, **kwds)
|
||||||
|
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.centralWidget = None
|
self.centralWidget = None
|
||||||
self.scene().clear()
|
self.scene().clear()
|
||||||
|
@ -18,12 +18,15 @@ class RemoteGraphicsView(QtGui.QWidget):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, parent=None, *args, **kwds):
|
def __init__(self, parent=None, *args, **kwds):
|
||||||
|
"""
|
||||||
|
The keyword arguments 'debug' and 'name', if specified, are passed to QtProcess.__init__().
|
||||||
|
"""
|
||||||
self._img = None
|
self._img = None
|
||||||
self._imgReq = None
|
self._imgReq = None
|
||||||
self._sizeHint = (640,480) ## no clue why this is needed, but it seems to be the default sizeHint for GraphicsView.
|
self._sizeHint = (640,480) ## no clue why this is needed, but it seems to be the default sizeHint for GraphicsView.
|
||||||
## without it, the widget will not compete for space against another GraphicsView.
|
## without it, the widget will not compete for space against another GraphicsView.
|
||||||
QtGui.QWidget.__init__(self)
|
QtGui.QWidget.__init__(self)
|
||||||
self._proc = mp.QtProcess(debug=kwds.pop('debug', False))
|
self._proc = mp.QtProcess(debug=kwds.pop('debug', False), name=kwds.pop('name', None))
|
||||||
self.pg = self._proc._import('pyqtgraph')
|
self.pg = self._proc._import('pyqtgraph')
|
||||||
self.pg.setConfigOptions(**self.pg.CONFIG_OPTIONS)
|
self.pg.setConfigOptions(**self.pg.CONFIG_OPTIONS)
|
||||||
rpgRemote = self._proc._import('pyqtgraph.widgets.RemoteGraphicsView')
|
rpgRemote = self._proc._import('pyqtgraph.widgets.RemoteGraphicsView')
|
||||||
@ -123,6 +126,7 @@ class Renderer(GraphicsView):
|
|||||||
|
|
||||||
def __init__(self, *args, **kwds):
|
def __init__(self, *args, **kwds):
|
||||||
## Create shared memory for rendered image
|
## Create shared memory for rendered image
|
||||||
|
#pg.dbg(namespace={'r': self})
|
||||||
if sys.platform.startswith('win'):
|
if sys.platform.startswith('win'):
|
||||||
self.shmtag = "pyqtgraph_shmem_" + ''.join([chr((random.getrandbits(20)%25) + 97) for i in range(20)])
|
self.shmtag = "pyqtgraph_shmem_" + ''.join([chr((random.getrandbits(20)%25) + 97) for i in range(20)])
|
||||||
self.shm = mmap.mmap(-1, mmap.PAGESIZE, self.shmtag) # use anonymous mmap on windows
|
self.shm = mmap.mmap(-1, mmap.PAGESIZE, self.shmtag) # use anonymous mmap on windows
|
||||||
@ -184,7 +188,11 @@ class Renderer(GraphicsView):
|
|||||||
self.img = QtGui.QImage(ch, self.width(), self.height(), QtGui.QImage.Format_ARGB32)
|
self.img = QtGui.QImage(ch, self.width(), self.height(), QtGui.QImage.Format_ARGB32)
|
||||||
else:
|
else:
|
||||||
address = ctypes.addressof(ctypes.c_char.from_buffer(self.shm, 0))
|
address = ctypes.addressof(ctypes.c_char.from_buffer(self.shm, 0))
|
||||||
|
try:
|
||||||
self.img = QtGui.QImage(sip.voidptr(address), self.width(), self.height(), QtGui.QImage.Format_ARGB32)
|
self.img = QtGui.QImage(sip.voidptr(address), self.width(), self.height(), QtGui.QImage.Format_ARGB32)
|
||||||
|
except TypeError:
|
||||||
|
# different versions of pyqt have different requirements here..
|
||||||
|
self.img = QtGui.QImage(memoryview(buffer(self.shm)), self.width(), self.height(), QtGui.QImage.Format_ARGB32)
|
||||||
self.img.fill(0xffffffff)
|
self.img.fill(0xffffffff)
|
||||||
p = QtGui.QPainter(self.img)
|
p = QtGui.QPainter(self.img)
|
||||||
self.render(p, self.viewRect(), self.rect())
|
self.render(p, self.viewRect(), self.rect())
|
||||||
|
Loading…
Reference in New Issue
Block a user