From 8899e8d858d0e4740f9a339a40647ca6808202c1 Mon Sep 17 00:00:00 2001
From: Luke Campagnola <>
Date: Wed, 26 Dec 2012 16:29:29 -0500
Subject: [PATCH] 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
---
examples/__main__.py | 15 +++--
examples/exampleLoaderTemplate.ui | 30 +++++++++
examples/exampleLoaderTemplate_pyqt.py | 18 ++++-
examples/exampleLoaderTemplate_pyside.py | 20 +++++-
examples/initExample.py | 12 +++-
exporters/ImageExporter.py | 18 +++--
exporters/PrintExporter.py | 16 +++--
exporters/SVGExporter.py | 2 +-
graphicsItems/ArrowItem.py | 5 ++
graphicsItems/GraphicsItem.py | 20 +++++-
graphicsItems/PlotCurveItem.py | 12 +---
graphicsItems/ScatterPlotItem.py | 43 ++++++------
graphicsItems/TextItem.py | 83 +++++++++++-------------
13 files changed, 194 insertions(+), 100 deletions(-)
diff --git a/examples/__main__.py b/examples/__main__.py
index 6f4bf138..1dbe7b9a 100644
--- a/examples/__main__.py
+++ b/examples/__main__.py
@@ -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'))
diff --git a/examples/exampleLoaderTemplate.ui b/examples/exampleLoaderTemplate.ui
index 1453240c..cd5ce921 100644
--- a/examples/exampleLoaderTemplate.ui
+++ b/examples/exampleLoaderTemplate.ui
@@ -57,6 +57,36 @@
+ -
+
+
-
+
+
+ Force Graphics System:
+
+
+
+ -
+
+
-
+
+ native
+
+
+ -
+
+ raster
+
+
+ -
+
+ opengl
+
+
+
+
+
+
-
diff --git a/examples/exampleLoaderTemplate_pyqt.py b/examples/exampleLoaderTemplate_pyqt.py
index 26e55a44..f359cc32 100644
--- a/examples/exampleLoaderTemplate_pyqt.py
+++ b/examples/exampleLoaderTemplate_pyqt.py
@@ -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))
diff --git a/examples/exampleLoaderTemplate_pyside.py b/examples/exampleLoaderTemplate_pyside.py
index a81f7299..113c1654 100644
--- a/examples/exampleLoaderTemplate_pyside.py
+++ b/examples/exampleLoaderTemplate_pyside.py
@@ -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))
diff --git a/examples/initExample.py b/examples/initExample.py
index 1b38363b..908f5fb0 100644
--- a/examples/initExample.py
+++ b/examples/initExample.py
@@ -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
+
diff --git a/exporters/ImageExporter.py b/exporters/ImageExporter.py
index 763b615d..cb6cf396 100644
--- a/exporters/ImageExporter.py
+++ b/exporters/ImageExporter.py
@@ -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()
diff --git a/exporters/PrintExporter.py b/exporters/PrintExporter.py
index 4a47af2e..5b31b45d 100644
--- a/exporters/PrintExporter.py
+++ b/exporters/PrintExporter.py
@@ -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()
diff --git a/exporters/SVGExporter.py b/exporters/SVGExporter.py
index 2d040282..134330d4 100644
--- a/exporters/SVGExporter.py
+++ b/exporters/SVGExporter.py
@@ -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)
diff --git a/graphicsItems/ArrowItem.py b/graphicsItems/ArrowItem.py
index 153ea712..22d0065b 100644
--- a/graphicsItems/ArrowItem.py
+++ b/graphicsItems/ArrowItem.py
@@ -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
\ No newline at end of file
diff --git a/graphicsItems/GraphicsItem.py b/graphicsItems/GraphicsItem.py
index 43b8148c..d3021b75 100644
--- a/graphicsItems/GraphicsItem.py
+++ b/graphicsItems/GraphicsItem.py
@@ -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
\ No newline at end of file
diff --git a/graphicsItems/PlotCurveItem.py b/graphicsItems/PlotCurveItem.py
index c49ce30b..dbbeb077 100644
--- a/graphicsItems/PlotCurveItem.py
+++ b/graphicsItems/PlotCurveItem.py
@@ -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."""
diff --git a/graphicsItems/ScatterPlotItem.py b/graphicsItems/ScatterPlotItem.py
index 2528d35b..2e41cb7c 100644
--- a/graphicsItems/ScatterPlotItem.py
+++ b/graphicsItems/ScatterPlotItem.py
@@ -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)
diff --git a/graphicsItems/TextItem.py b/graphicsItems/TextItem.py
index a85e919d..b5666f6e 100644
--- a/graphicsItems/TextItem.py
+++ b/graphicsItems/TextItem.py
@@ -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 = '%s' % (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)
\ No newline at end of file