Updated image, SVG, and print exporters. Image export works well; SVG and print still need work.
Added ability to run examples with a specific Qt graphics system
This commit is contained in:
parent
a157d9c4fa
commit
8899e8d858
@ -126,6 +126,9 @@ class ExampleLoader(QtGui.QMainWindow):
|
||||
extra.append('pyqt')
|
||||
elif self.ui.pysideCheck.isChecked():
|
||||
extra.append('pyside')
|
||||
|
||||
if self.ui.forceGraphicsCheck.isChecked():
|
||||
extra.append(str(self.ui.forceGraphicsCombo.currentText()))
|
||||
|
||||
if fn is None:
|
||||
return
|
||||
@ -163,22 +166,26 @@ def buildFileList(examples, files=None):
|
||||
buildFileList(val, files)
|
||||
return files
|
||||
|
||||
def testFile(name, f, exe, lib):
|
||||
def testFile(name, f, exe, lib, graphicsSystem):
|
||||
global path
|
||||
fn = os.path.join(path,f)
|
||||
#print "starting process: ", fn
|
||||
|
||||
os.chdir(path)
|
||||
sys.stdout.write(name)
|
||||
sys.stdout.flush()
|
||||
|
||||
import1 = "import %s" % lib if lib != '' else ''
|
||||
import2 = os.path.splitext(os.path.split(fn)[1])[0]
|
||||
graphicsSystem = '' if graphicsSystem is None else "pg.QtGui.QApplication.setGraphicsSystem('%s')" % graphicsSystem
|
||||
code = """
|
||||
try:
|
||||
%s
|
||||
import pyqtgraph as pg
|
||||
%s
|
||||
import %s
|
||||
import sys
|
||||
print("test complete")
|
||||
sys.stdout.flush()
|
||||
import pyqtgraph as pg
|
||||
import time
|
||||
while True: ## run a little event loop
|
||||
pg.QtGui.QApplication.processEvents()
|
||||
@ -187,7 +194,7 @@ except:
|
||||
print("test failed")
|
||||
raise
|
||||
|
||||
""" % ("import %s" % lib if lib != '' else "", os.path.splitext(os.path.split(fn)[1])[0])
|
||||
""" % (import1, import2, graphicsSystem)
|
||||
#print code
|
||||
process = subprocess.Popen(['exec %s -i' % (exe)], shell=True, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
process.stdin.write(code.encode('UTF-8'))
|
||||
|
@ -57,6 +57,36 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="forceGraphicsCheck">
|
||||
<property name="text">
|
||||
<string>Force Graphics System:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="forceGraphicsCombo">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>native</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>raster</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>opengl</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="loadBtn">
|
||||
<property name="text">
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# Form implementation generated from reading ui file './examples/exampleLoaderTemplate.ui'
|
||||
#
|
||||
# Created: Fri Oct 26 07:53:55 2012
|
||||
# Created: Mon Dec 24 00:33:38 2012
|
||||
# by: PyQt4 UI code generator 4.9.1
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
@ -44,6 +44,18 @@ class Ui_Form(object):
|
||||
self.pysideCheck.setObjectName(_fromUtf8("pysideCheck"))
|
||||
self.horizontalLayout.addWidget(self.pysideCheck)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||
self.horizontalLayout_2 = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2"))
|
||||
self.forceGraphicsCheck = QtGui.QCheckBox(self.layoutWidget)
|
||||
self.forceGraphicsCheck.setObjectName(_fromUtf8("forceGraphicsCheck"))
|
||||
self.horizontalLayout_2.addWidget(self.forceGraphicsCheck)
|
||||
self.forceGraphicsCombo = QtGui.QComboBox(self.layoutWidget)
|
||||
self.forceGraphicsCombo.setObjectName(_fromUtf8("forceGraphicsCombo"))
|
||||
self.forceGraphicsCombo.addItem(_fromUtf8(""))
|
||||
self.forceGraphicsCombo.addItem(_fromUtf8(""))
|
||||
self.forceGraphicsCombo.addItem(_fromUtf8(""))
|
||||
self.horizontalLayout_2.addWidget(self.forceGraphicsCombo)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout_2)
|
||||
self.loadBtn = QtGui.QPushButton(self.layoutWidget)
|
||||
self.loadBtn.setObjectName(_fromUtf8("loadBtn"))
|
||||
self.verticalLayout.addWidget(self.loadBtn)
|
||||
@ -62,5 +74,9 @@ class Ui_Form(object):
|
||||
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.pyqtCheck.setText(QtGui.QApplication.translate("Form", "Force PyQt", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.pysideCheck.setText(QtGui.QApplication.translate("Form", "Force PySide", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.forceGraphicsCheck.setText(QtGui.QApplication.translate("Form", "Force Graphics System:", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.forceGraphicsCombo.setItemText(0, QtGui.QApplication.translate("Form", "native", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.forceGraphicsCombo.setItemText(1, QtGui.QApplication.translate("Form", "raster", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.forceGraphicsCombo.setItemText(2, QtGui.QApplication.translate("Form", "opengl", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.loadBtn.setText(QtGui.QApplication.translate("Form", "Load Example", None, QtGui.QApplication.UnicodeUTF8))
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
# Form implementation generated from reading ui file './examples/exampleLoaderTemplate.ui'
|
||||
#
|
||||
# Created: Fri Oct 26 07:53:57 2012
|
||||
# by: pyside-uic 0.2.13 running on PySide 1.1.0
|
||||
# Created: Mon Dec 24 00:33:39 2012
|
||||
# by: pyside-uic 0.2.13 running on PySide 1.1.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
@ -39,6 +39,18 @@ class Ui_Form(object):
|
||||
self.pysideCheck.setObjectName("pysideCheck")
|
||||
self.horizontalLayout.addWidget(self.pysideCheck)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||
self.horizontalLayout_2 = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
self.forceGraphicsCheck = QtGui.QCheckBox(self.layoutWidget)
|
||||
self.forceGraphicsCheck.setObjectName("forceGraphicsCheck")
|
||||
self.horizontalLayout_2.addWidget(self.forceGraphicsCheck)
|
||||
self.forceGraphicsCombo = QtGui.QComboBox(self.layoutWidget)
|
||||
self.forceGraphicsCombo.setObjectName("forceGraphicsCombo")
|
||||
self.forceGraphicsCombo.addItem("")
|
||||
self.forceGraphicsCombo.addItem("")
|
||||
self.forceGraphicsCombo.addItem("")
|
||||
self.horizontalLayout_2.addWidget(self.forceGraphicsCombo)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout_2)
|
||||
self.loadBtn = QtGui.QPushButton(self.layoutWidget)
|
||||
self.loadBtn.setObjectName("loadBtn")
|
||||
self.verticalLayout.addWidget(self.loadBtn)
|
||||
@ -57,5 +69,9 @@ class Ui_Form(object):
|
||||
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.pyqtCheck.setText(QtGui.QApplication.translate("Form", "Force PyQt", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.pysideCheck.setText(QtGui.QApplication.translate("Form", "Force PySide", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.forceGraphicsCheck.setText(QtGui.QApplication.translate("Form", "Force Graphics System:", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.forceGraphicsCombo.setItemText(0, QtGui.QApplication.translate("Form", "native", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.forceGraphicsCombo.setItemText(1, QtGui.QApplication.translate("Form", "raster", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.forceGraphicsCombo.setItemText(2, QtGui.QApplication.translate("Form", "opengl", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.loadBtn.setText(QtGui.QApplication.translate("Form", "Load Example", None, QtGui.QApplication.UnicodeUTF8))
|
||||
|
||||
|
@ -3,6 +3,14 @@ import sys, os
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')))
|
||||
|
||||
if 'pyside' in sys.argv: ## should force example to use PySide instead of PyQt
|
||||
import PySide
|
||||
from PySide import QtGui
|
||||
elif 'pyqt' in sys.argv:
|
||||
import PyQt4
|
||||
from PyQt4 import QtGui
|
||||
else:
|
||||
from pyqtgraph.Qt import QtGui
|
||||
|
||||
for gs in ['raster', 'native', 'opengl']:
|
||||
if gs in sys.argv:
|
||||
QtGui.QApplication.setGraphicsSystem(gs)
|
||||
break
|
||||
|
||||
|
@ -27,12 +27,12 @@ class ImageExporter(Exporter):
|
||||
|
||||
def widthChanged(self):
|
||||
sr = self.getSourceRect()
|
||||
ar = sr.height() / sr.width()
|
||||
ar = float(sr.height()) / sr.width()
|
||||
self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged)
|
||||
|
||||
def heightChanged(self):
|
||||
sr = self.getSourceRect()
|
||||
ar = sr.width() / sr.height()
|
||||
ar = float(sr.width()) / sr.height()
|
||||
self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged)
|
||||
|
||||
def parameters(self):
|
||||
@ -51,6 +51,8 @@ class ImageExporter(Exporter):
|
||||
|
||||
targetRect = QtCore.QRect(0, 0, self.params['width'], self.params['height'])
|
||||
sourceRect = self.getSourceRect()
|
||||
|
||||
|
||||
#self.png = QtGui.QImage(targetRect.size(), QtGui.QImage.Format_ARGB32)
|
||||
#self.png.fill(pyqtgraph.mkColor(self.params['background']))
|
||||
bg = np.empty((self.params['width'], self.params['height'], 4), dtype=np.ubyte)
|
||||
@ -60,11 +62,19 @@ class ImageExporter(Exporter):
|
||||
bg[:,:,2] = color.red()
|
||||
bg[:,:,3] = color.alpha()
|
||||
self.png = pg.makeQImage(bg, alpha=True)
|
||||
|
||||
## set resolution of image:
|
||||
origTargetRect = self.getTargetRect()
|
||||
resolutionScale = targetRect.width() / origTargetRect.width()
|
||||
#self.png.setDotsPerMeterX(self.png.dotsPerMeterX() * resolutionScale)
|
||||
#self.png.setDotsPerMeterY(self.png.dotsPerMeterY() * resolutionScale)
|
||||
|
||||
painter = QtGui.QPainter(self.png)
|
||||
#dtr = painter.deviceTransform()
|
||||
try:
|
||||
self.setExportMode(True, {'antialias': self.params['antialias'], 'background': self.params['background']})
|
||||
self.setExportMode(True, {'antialias': self.params['antialias'], 'background': self.params['background'], 'painter': painter, 'resolutionScale': resolutionScale})
|
||||
painter.setRenderHint(QtGui.QPainter.Antialiasing, self.params['antialias'])
|
||||
self.getScene().render(painter, QtCore.QRectF(targetRect), sourceRect)
|
||||
self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect))
|
||||
finally:
|
||||
self.setExportMode(False)
|
||||
painter.end()
|
||||
|
@ -3,8 +3,8 @@ from pyqtgraph.parametertree import Parameter
|
||||
from pyqtgraph.Qt import QtGui, QtCore, QtSvg
|
||||
import re
|
||||
|
||||
#__all__ = ['PrintExporter']
|
||||
__all__ = [] ## Printer is disabled for now--does not work very well.
|
||||
__all__ = ['PrintExporter']
|
||||
#__all__ = [] ## Printer is disabled for now--does not work very well.
|
||||
|
||||
class PrintExporter(Exporter):
|
||||
Name = "Printer"
|
||||
@ -38,9 +38,15 @@ class PrintExporter(Exporter):
|
||||
if dialog.exec_() != QtGui.QDialog.Accepted:
|
||||
return;
|
||||
|
||||
#dpi = QtGui.QDesktopWidget().physicalDpiX()
|
||||
|
||||
#self.svg.setSize(QtCore.QSize(100,100))
|
||||
#self.svg.setResolution(600)
|
||||
res = printer.resolution()
|
||||
#res = printer.resolution()
|
||||
sr = self.getSourceRect()
|
||||
#res = sr.width() * .4 / (self.params['width'] * 100 / 2.54)
|
||||
res = QtGui.QDesktopWidget().physicalDpiX()
|
||||
printer.setResolution(res)
|
||||
rect = printer.pageRect()
|
||||
center = rect.center()
|
||||
h = self.params['height'] * res * 100. / 2.54
|
||||
@ -52,8 +58,8 @@ class PrintExporter(Exporter):
|
||||
sourceRect = self.getSourceRect()
|
||||
painter = QtGui.QPainter(printer)
|
||||
try:
|
||||
self.setExportMode(True)
|
||||
self.getScene().render(painter, QtCore.QRectF(targetRect), sourceRect)
|
||||
self.setExportMode(True, {'painter': painter})
|
||||
self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect))
|
||||
finally:
|
||||
self.setExportMode(False)
|
||||
painter.end()
|
||||
|
@ -46,7 +46,7 @@ class SVGExporter(Exporter):
|
||||
|
||||
painter = QtGui.QPainter(self.svg)
|
||||
try:
|
||||
self.setExportMode(True)
|
||||
self.setExportMode(True, {'painter': painter,})
|
||||
self.render(painter, QtCore.QRectF(targetRect), sourceRect)
|
||||
finally:
|
||||
self.setExportMode(False)
|
||||
|
@ -54,3 +54,8 @@ class ArrowItem(QtGui.QGraphicsPathItem):
|
||||
def paint(self, p, *args):
|
||||
p.setRenderHint(QtGui.QPainter.Antialiasing)
|
||||
QtGui.QGraphicsPathItem.paint(self, p, *args)
|
||||
|
||||
def shape(self):
|
||||
#if not self.opts['pxMode']:
|
||||
#return QtGui.QGraphicsPathItem.shape(self)
|
||||
return self.path
|
@ -28,10 +28,13 @@ class GraphicsItem(object):
|
||||
self._viewWidget = None
|
||||
self._viewBox = None
|
||||
self._connectedView = None
|
||||
self._exportOpts = False ## If False, not currently exporting. Otherwise, contains dict of export options.
|
||||
if register:
|
||||
GraphicsScene.registerObject(self) ## workaround for pyqt bug in graphicsscene.items()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def getViewWidget(self):
|
||||
"""
|
||||
Return the view widget for this item. If the scene has multiple views, only the first view is returned.
|
||||
@ -82,6 +85,9 @@ class GraphicsItem(object):
|
||||
Return the transform that converts local item coordinates to device coordinates (usually pixels).
|
||||
Extends deviceTransform to automatically determine the viewportTransform.
|
||||
"""
|
||||
if self._exportOpts is not False and 'painter' in self._exportOpts: ## currently exporting; device transform may be different.
|
||||
return self._exportOpts['painter'].deviceTransform()
|
||||
|
||||
if viewportTransform is None:
|
||||
view = self.getViewWidget()
|
||||
if view is None:
|
||||
@ -476,4 +482,16 @@ class GraphicsItem(object):
|
||||
return tree
|
||||
|
||||
|
||||
def setExportMode(self, export, opts):
|
||||
"""
|
||||
This method is called by exporters to inform items that they are being drawn for export
|
||||
with a specific set of options. Items access these via self._exportOptions.
|
||||
When exporting is complete, _exportOptions is set to False.
|
||||
"""
|
||||
if export:
|
||||
self._exportOpts = opts
|
||||
#if 'antialias' not in opts:
|
||||
#self._exportOpts['antialias'] = True
|
||||
else:
|
||||
self._exportOpts = False
|
||||
|
@ -52,7 +52,6 @@ class PlotCurveItem(GraphicsObject):
|
||||
self.clear()
|
||||
self.path = None
|
||||
self.fillPath = None
|
||||
self.exportOpts = False
|
||||
|
||||
|
||||
## this is disastrous for performance.
|
||||
@ -404,8 +403,8 @@ class PlotCurveItem(GraphicsObject):
|
||||
path = self.path
|
||||
prof.mark('generate path')
|
||||
|
||||
if self.exportOpts is not False:
|
||||
aa = self.exportOpts['antialias']
|
||||
if self._exportOpts is not False:
|
||||
aa = self._exportOpts.get('antialias', True)
|
||||
else:
|
||||
aa = self.opts['antialias']
|
||||
|
||||
@ -487,13 +486,6 @@ class PlotCurveItem(GraphicsObject):
|
||||
ev.accept()
|
||||
self.sigClicked.emit(self)
|
||||
|
||||
def setExportMode(self, export, opts):
|
||||
if export:
|
||||
self.exportOpts = opts
|
||||
if 'antialias' not in opts:
|
||||
self.exportOpts['antialias'] = True
|
||||
else:
|
||||
self.exportOpts = False
|
||||
|
||||
class ROIPlotItem(PlotCurveItem):
|
||||
"""Plot curve that monitors an ROI and image for changes to automatically replot."""
|
||||
|
@ -239,7 +239,6 @@ class ScatterPlotItem(GraphicsObject):
|
||||
'useCache': True, ## If useCache is False, symbols are re-drawn on every paint.
|
||||
'antialias': pg.getConfigOption('antialias'),
|
||||
}
|
||||
self.exportOpts = False
|
||||
|
||||
self.setPen(200,200,200, update=False)
|
||||
self.setBrush(100,100,150, update=False)
|
||||
@ -546,7 +545,7 @@ class ScatterPlotItem(GraphicsObject):
|
||||
if invalidate:
|
||||
self.invalidate()
|
||||
|
||||
def getSpotOpts(self, recs):
|
||||
def getSpotOpts(self, recs, scale=1.0):
|
||||
if recs.ndim == 0:
|
||||
rec = recs
|
||||
symbol = rec['symbol']
|
||||
@ -561,11 +560,12 @@ class ScatterPlotItem(GraphicsObject):
|
||||
brush = rec['brush']
|
||||
if brush is None:
|
||||
brush = self.opts['brush']
|
||||
return (symbol, size, fn.mkPen(pen), fn.mkBrush(brush))
|
||||
return (symbol, size*scale, fn.mkPen(pen), fn.mkBrush(brush))
|
||||
else:
|
||||
recs = recs.copy()
|
||||
recs['symbol'][np.equal(recs['symbol'], None)] = self.opts['symbol']
|
||||
recs['size'][np.equal(recs['size'], -1)] = self.opts['size']
|
||||
recs['size'] *= scale
|
||||
recs['pen'][np.equal(recs['pen'], None)] = fn.mkPen(self.opts['pen'])
|
||||
recs['brush'][np.equal(recs['brush'], None)] = fn.mkBrush(self.opts['brush'])
|
||||
return recs
|
||||
@ -675,18 +675,20 @@ class ScatterPlotItem(GraphicsObject):
|
||||
rect = QtCore.QRectF(y, x, h, w)
|
||||
self.fragments.append(QtGui.QPainter.PixmapFragment.create(pos, rect))
|
||||
|
||||
def setExportMode(self, export, opts):
|
||||
if export:
|
||||
self.exportOpts = opts
|
||||
if 'antialias' not in opts:
|
||||
self.exportOpts['antialias'] = True
|
||||
else:
|
||||
self.exportOpts = False
|
||||
|
||||
def setExportMode(self, *args, **kwds):
|
||||
GraphicsObject.setExportMode(self, *args, **kwds)
|
||||
self.invalidate()
|
||||
|
||||
def paint(self, p, *args):
|
||||
#p.setPen(fn.mkPen('r'))
|
||||
#p.drawRect(self.boundingRect())
|
||||
if self._exportOpts is not False:
|
||||
aa = self._exportOpts.get('antialias', True)
|
||||
scale = self._exportOpts.get('resolutionScale', 1.0) ## exporting to image; pixel resolution may have changed
|
||||
else:
|
||||
aa = self.opts['antialias']
|
||||
scale = 1.0
|
||||
|
||||
if self.opts['pxMode'] is True:
|
||||
atlas = self.fragmentAtlas.getAtlas()
|
||||
#arr = fn.imageToArray(atlas.toImage(), copy=True)
|
||||
@ -701,13 +703,9 @@ class ScatterPlotItem(GraphicsObject):
|
||||
|
||||
p.resetTransform()
|
||||
|
||||
if not USE_PYSIDE and self.opts['useCache'] and self.exportOpts is False:
|
||||
if not USE_PYSIDE and self.opts['useCache'] and self._exportOpts is False:
|
||||
p.drawPixmapFragments(self.fragments, atlas)
|
||||
else:
|
||||
if self.exportOpts is not False:
|
||||
aa = self.exportOpts['antialias']
|
||||
else:
|
||||
aa = self.opts['antialias']
|
||||
p.setRenderHint(p.Antialiasing, aa)
|
||||
|
||||
for i in range(len(self.data)):
|
||||
@ -715,23 +713,20 @@ class ScatterPlotItem(GraphicsObject):
|
||||
frag = self.fragments[i]
|
||||
p.resetTransform()
|
||||
p.translate(frag.x, frag.y)
|
||||
drawSymbol(p, *self.getSpotOpts(rec))
|
||||
drawSymbol(p, *self.getSpotOpts(rec, scale))
|
||||
else:
|
||||
if self.picture is None:
|
||||
self.picture = QtGui.QPicture()
|
||||
p2 = QtGui.QPainter(self.picture)
|
||||
for rec in self.data:
|
||||
|
||||
if scale != 1.0:
|
||||
rec = rec.copy()
|
||||
rec['size'] *= scale
|
||||
p2.resetTransform()
|
||||
p2.translate(rec['x'], rec['y'])
|
||||
drawSymbol(p2, *self.getSpotOpts(rec))
|
||||
drawSymbol(p2, *self.getSpotOpts(rec, scale))
|
||||
p2.end()
|
||||
|
||||
if self.exportOpts is not False:
|
||||
aa = self.exportOpts['antialias']
|
||||
else:
|
||||
aa = self.opts['antialias']
|
||||
p.setRenderHint(p.Antialiasing, aa)
|
||||
self.picture.play(p)
|
||||
|
||||
|
||||
|
@ -27,25 +27,27 @@ class TextItem(UIGraphicsItem):
|
||||
#*angle* Angle in degrees to rotate text (note that the rotation assigned in this item's
|
||||
#transformation will be ignored)
|
||||
|
||||
|
||||
self.anchor = pg.Point(anchor)
|
||||
#self.angle = 0
|
||||
UIGraphicsItem.__init__(self)
|
||||
self.textItem = QtGui.QGraphicsTextItem()
|
||||
self.textItem.setParentItem(self)
|
||||
self.lastTransform = None
|
||||
self._bounds = QtCore.QRectF()
|
||||
if html is None:
|
||||
self.setText(text, color)
|
||||
else:
|
||||
self.setHtml(html)
|
||||
self.anchor = pg.Point(anchor)
|
||||
self.fill = pg.mkBrush(fill)
|
||||
self.border = pg.mkPen(border)
|
||||
self.angle = angle
|
||||
#self.setFlag(self.ItemIgnoresTransformations) ## This is required to keep the text unscaled inside the viewport
|
||||
self.rotate(angle)
|
||||
self.setFlag(self.ItemIgnoresTransformations) ## This is required to keep the text unscaled inside the viewport
|
||||
|
||||
def setText(self, text, color=(200,200,200)):
|
||||
color = pg.mkColor(color)
|
||||
self.textItem.setDefaultTextColor(color)
|
||||
self.textItem.setPlainText(text)
|
||||
self.updateText()
|
||||
#html = '<span style="color: #%s; text-align: center;">%s</span>' % (color, text)
|
||||
#self.setHtml(html)
|
||||
|
||||
@ -70,38 +72,41 @@ class TextItem(UIGraphicsItem):
|
||||
self.textItem.setFont(*args)
|
||||
self.updateText()
|
||||
|
||||
def updateText(self):
|
||||
self.viewRangeChanged()
|
||||
|
||||
#def getImage(self):
|
||||
#if self.img is None:
|
||||
#br = self.textItem.boundingRect()
|
||||
#img = QtGui.QImage(int(br.width()), int(br.height()), QtGui.QImage.Format_ARGB32)
|
||||
#p = QtGui.QPainter(img)
|
||||
#self.textItem.paint(p, QtGui.QStyleOptionGraphicsItem(), None)
|
||||
#p.end()
|
||||
#self.img = img
|
||||
#return self.img
|
||||
#def setAngle(self, angle):
|
||||
#self.angle = angle
|
||||
#self.updateText()
|
||||
|
||||
def textBoundingRect(self):
|
||||
## return the bounds of the text box in device coordinates
|
||||
pos = self.mapToDevice(QtCore.QPointF(0,0))
|
||||
if pos is None:
|
||||
return None
|
||||
tbr = self.textItem.boundingRect()
|
||||
return QtCore.QRectF(pos.x() - tbr.width()*self.anchor.x(), pos.y() - tbr.height()*self.anchor.y(), tbr.width(), tbr.height())
|
||||
|
||||
def updateText(self):
|
||||
|
||||
## Needed to maintain font size when rendering to image with increased resolution
|
||||
self.textItem.resetTransform()
|
||||
#self.textItem.rotate(self.angle)
|
||||
if self._exportOpts is not False and 'resolutionScale' in self._exportOpts:
|
||||
s = self._exportOpts['resolutionScale']
|
||||
self.textItem.scale(s, s)
|
||||
|
||||
#br = self.textItem.mapRectToParent(self.textItem.boundingRect())
|
||||
self.textItem.setPos(0,0)
|
||||
br = self.textItem.boundingRect()
|
||||
apos = self.textItem.mapToParent(pg.Point(br.width()*self.anchor.x(), br.height()*self.anchor.y()))
|
||||
#print br, apos
|
||||
self.textItem.setPos(-apos.x(), -apos.y())
|
||||
|
||||
#def textBoundingRect(self):
|
||||
### return the bounds of the text box in device coordinates
|
||||
#pos = self.mapToDevice(QtCore.QPointF(0,0))
|
||||
#if pos is None:
|
||||
#return None
|
||||
#tbr = self.textItem.boundingRect()
|
||||
#return QtCore.QRectF(pos.x() - tbr.width()*self.anchor.x(), pos.y() - tbr.height()*self.anchor.y(), tbr.width(), tbr.height())
|
||||
|
||||
|
||||
def viewRangeChanged(self):
|
||||
br = self.textBoundingRect()
|
||||
if br is None:
|
||||
return
|
||||
self.prepareGeometryChange()
|
||||
self._bounds = fn.invertQTransform(self.deviceTransform()).mapRect(br)
|
||||
#print self._bounds
|
||||
self.updateText()
|
||||
|
||||
def boundingRect(self):
|
||||
return self._bounds
|
||||
return self.textItem.mapToParent(self.textItem.boundingRect()).boundingRect()
|
||||
|
||||
def paint(self, p, *args):
|
||||
tr = p.transform()
|
||||
@ -110,23 +115,9 @@ class TextItem(UIGraphicsItem):
|
||||
self.viewRangeChanged()
|
||||
self.lastTransform = tr
|
||||
|
||||
|
||||
tbr = self.textBoundingRect()
|
||||
|
||||
#p.setPen(pg.mkPen('r'))
|
||||
#p.drawRect(self.boundingRect())
|
||||
|
||||
p.setPen(self.border)
|
||||
p.setBrush(self.fill)
|
||||
p.setRenderHint(p.Antialiasing, True)
|
||||
p.drawPolygon(self.textItem.mapToParent(self.textItem.boundingRect()))
|
||||
|
||||
|
||||
#p.fillRect(tbr)
|
||||
p.resetTransform()
|
||||
#p.drawRect(tbr)
|
||||
|
||||
|
||||
p.translate(tbr.left(), tbr.top())
|
||||
p.rotate(self.angle)
|
||||
p.drawRect(QtCore.QRectF(0, 0, tbr.width(), tbr.height()))
|
||||
self.textItem.paint(p, QtGui.QStyleOptionGraphicsItem(), None)
|
||||
|
Loading…
Reference in New Issue
Block a user