Minor updates for exporting
- curves enable antialiasing when exporting to image - plotitems hide button during export
This commit is contained in:
parent
7c94b5a702
commit
b78662c33e
@ -59,12 +59,12 @@ class GraphicsScene(QtGui.QGraphicsScene):
|
||||
move in a drag.
|
||||
"""
|
||||
|
||||
|
||||
_addressCache = weakref.WeakValueDictionary()
|
||||
sigMouseHover = QtCore.Signal(object) ## emits a list of objects hovered over
|
||||
sigMouseMoved = QtCore.Signal(object) ## emits position of mouse on every move
|
||||
sigMouseClicked = QtCore.Signal(object) ## emitted when MouseClickEvent is not accepted by any items under the click.
|
||||
|
||||
_addressCache = weakref.WeakValueDictionary()
|
||||
|
||||
ExportDirectory = None
|
||||
|
||||
@classmethod
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# Form implementation generated from reading ui file 'exportDialogTemplate.ui'
|
||||
#
|
||||
# Created: Sat Mar 10 17:54:53 2012
|
||||
# Created: Thu Mar 22 13:13:06 2012
|
||||
# by: PyQt4 UI code generator 4.8.5
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
@ -18,7 +18,7 @@ class Ui_Form(object):
|
||||
def setupUi(self, Form):
|
||||
Form.setObjectName(_fromUtf8("Form"))
|
||||
Form.resize(241, 367)
|
||||
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
|
||||
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Export", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.gridLayout = QtGui.QGridLayout(Form)
|
||||
self.gridLayout.setSpacing(0)
|
||||
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||
|
@ -11,7 +11,7 @@
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
<string>Export</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="spacing">
|
||||
|
@ -75,8 +75,74 @@ class Exporter(object):
|
||||
else:
|
||||
return self.item.mapRectToDevice(self.item.boundingRect())
|
||||
|
||||
def setExportMode(self, export, opts=None):
|
||||
"""
|
||||
Call setExportMode(export, opts) on all items that will
|
||||
be painted during the export. This informs the item
|
||||
that it is about to be painted for export, allowing it to
|
||||
alter its appearance temporarily
|
||||
|
||||
|
||||
|
||||
*export* - bool; must be True before exporting and False afterward
|
||||
*opts* - dict; common parameters are 'antialias' and 'background'
|
||||
"""
|
||||
if opts is None:
|
||||
opts = {}
|
||||
for item in self.getPaintItems():
|
||||
if hasattr(item, 'setExportMode'):
|
||||
item.setExportMode(export, opts)
|
||||
|
||||
def getPaintItems(self, root=None):
|
||||
"""Return a list of all items that should be painted in the correct order."""
|
||||
if root is None:
|
||||
root = self.item
|
||||
preItems = []
|
||||
postItems = []
|
||||
if isinstance(root, QtGui.QGraphicsScene):
|
||||
childs = [i for i in root.items() if i.parentItem() is None]
|
||||
rootItem = []
|
||||
else:
|
||||
childs = root.childItems()
|
||||
rootItem = [root]
|
||||
childs.sort(lambda a,b: cmp(a.zValue(), b.zValue()))
|
||||
while len(childs) > 0:
|
||||
ch = childs.pop(0)
|
||||
tree = self.getPaintItems(ch)
|
||||
if int(ch.flags() & ch.ItemStacksBehindParent) > 0 or (ch.zValue() < 0 and int(ch.flags() & ch.ItemNegativeZStacksBehindParent) > 0):
|
||||
preItems.extend(tree)
|
||||
else:
|
||||
postItems.extend(tree)
|
||||
|
||||
return preItems + rootItem + postItems
|
||||
|
||||
def render(self, painter, sourcRect, targetRect, item=None)
|
||||
|
||||
#if item is None:
|
||||
#item = self.item
|
||||
#preItems = []
|
||||
#postItems = []
|
||||
#if isinstance(item, QtGui.QGraphicsScene):
|
||||
#childs = [i for i in item.items() if i.parentItem() is None]
|
||||
#rootItem = []
|
||||
#else:
|
||||
#childs = item.childItems()
|
||||
#rootItem = [item]
|
||||
#childs.sort(lambda a,b: cmp(a.zValue(), b.zValue()))
|
||||
#while len(childs) > 0:
|
||||
#ch = childs.pop(0)
|
||||
#if int(ch.flags() & ch.ItemStacksBehindParent) > 0 or (ch.zValue() < 0 and int(ch.flags() & ch.ItemNegativeZStacksBehindParent) > 0):
|
||||
#preItems.extend(tree)
|
||||
#else:
|
||||
#postItems.extend(tree)
|
||||
|
||||
#for ch in preItems:
|
||||
#self.render(painter, sourceRect, targetRect, item=ch)
|
||||
### paint root here
|
||||
#for ch in postItems:
|
||||
#self.render(painter, sourceRect, targetRect, item=ch)
|
||||
|
||||
|
||||
self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect))
|
||||
|
||||
#def writePs(self, fileName=None, item=None):
|
||||
#if fileName is None:
|
||||
|
@ -57,6 +57,12 @@ class ImageExporter(Exporter):
|
||||
bg[:,:,3] = color.alpha()
|
||||
self.png = pg.makeQImage(bg, alpha=True)
|
||||
painter = QtGui.QPainter(self.png)
|
||||
self.getScene().render(painter, QtCore.QRectF(targetRect), sourceRect)
|
||||
try:
|
||||
self.setExportMode(True, {'antialias': self.params['antialias'], 'background': self.params['background']})
|
||||
self.getScene().render(painter, QtCore.QRectF(targetRect), sourceRect)
|
||||
finally:
|
||||
self.setExportMode(False)
|
||||
self.png.save(fileName)
|
||||
painter.end()
|
||||
painter.end()
|
||||
|
||||
|
59
exporters/PrintExporter.py
Normal file
59
exporters/PrintExporter.py
Normal file
@ -0,0 +1,59 @@
|
||||
from Exporter import Exporter
|
||||
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.
|
||||
|
||||
class PrintExporter(Exporter):
|
||||
Name = "Printer"
|
||||
def __init__(self, item):
|
||||
Exporter.__init__(self, item)
|
||||
tr = self.getTargetRect()
|
||||
self.params = Parameter(name='params', type='group', children=[
|
||||
{'name': 'width', 'type': 'float', 'value': 0.1, 'limits': (0, None), 'suffix': 'm', 'siPrefix': True},
|
||||
{'name': 'height', 'type': 'float', 'value': (0.1 * tr.height()) / tr.width(), 'limits': (0, None), 'suffix': 'm', 'siPrefix': True},
|
||||
])
|
||||
self.params.param('width').sigValueChanged.connect(self.widthChanged)
|
||||
self.params.param('height').sigValueChanged.connect(self.heightChanged)
|
||||
|
||||
def widthChanged(self):
|
||||
sr = self.getSourceRect()
|
||||
ar = 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()
|
||||
self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged)
|
||||
|
||||
def parameters(self):
|
||||
return self.params
|
||||
|
||||
def export(self, fileName=None):
|
||||
printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
|
||||
dialog = QtGui.QPrintDialog(printer)
|
||||
dialog.setWindowTitle("Print Document")
|
||||
if dialog.exec_() != QtGui.QDialog.Accepted:
|
||||
return;
|
||||
|
||||
#self.svg.setSize(QtCore.QSize(100,100))
|
||||
#self.svg.setResolution(600)
|
||||
res = printer.resolution()
|
||||
rect = printer.pageRect()
|
||||
center = rect.center()
|
||||
h = self.params['height'] * res * 100. / 2.54
|
||||
w = self.params['width'] * res * 100. / 2.54
|
||||
x = center.x() - w/2.
|
||||
y = center.y() - h/2.
|
||||
|
||||
targetRect = QtCore.QRect(x, y, w, h)
|
||||
sourceRect = self.getSourceRect()
|
||||
painter = QtGui.QPainter(printer)
|
||||
try:
|
||||
self.setExportMode(True)
|
||||
self.getScene().render(painter, QtCore.QRectF(targetRect), sourceRect)
|
||||
finally:
|
||||
self.setExportMode(False)
|
||||
painter.end()
|
@ -42,7 +42,11 @@ class SVGExporter(Exporter):
|
||||
targetRect = QtCore.QRect(0, 0, self.params['width'], self.params['height'])
|
||||
sourceRect = self.getSourceRect()
|
||||
painter = QtGui.QPainter(self.svg)
|
||||
self.getScene().render(painter, QtCore.QRectF(targetRect), sourceRect)
|
||||
try:
|
||||
self.setExportMode(True)
|
||||
self.render(painter, QtCore.QRectF(targetRect), sourceRect)
|
||||
finally:
|
||||
self.setExportMode(False)
|
||||
painter.end()
|
||||
|
||||
## Workaround to set pen widths correctly
|
||||
|
@ -1,6 +1,24 @@
|
||||
from SVGExporter import *
|
||||
from ImageExporter import *
|
||||
Exporters = [SVGExporter, ImageExporter]
|
||||
Exporters = []
|
||||
|
||||
import os, sys
|
||||
d = os.path.split(__file__)[0]
|
||||
files = []
|
||||
for f in os.listdir(d):
|
||||
if os.path.isdir(os.path.join(d, f)):
|
||||
files.append(f)
|
||||
elif f[-3:] == '.py' and f not in ['__init__.py', 'Exporter.py']:
|
||||
files.append(f[:-3])
|
||||
|
||||
for modName in files:
|
||||
mod = __import__(modName, globals(), locals(), fromlist=['*'])
|
||||
if hasattr(mod, '__all__'):
|
||||
names = mod.__all__
|
||||
else:
|
||||
names = [n for n in dir(mod) if n[0] != '_']
|
||||
for k in names:
|
||||
if hasattr(mod, k):
|
||||
Exporters.append(getattr(mod, k))
|
||||
|
||||
|
||||
def listExporters():
|
||||
return Exporters[:]
|
||||
|
@ -261,6 +261,9 @@ class AxisItem(GraphicsWidget):
|
||||
|
||||
def drawPicture(self, p):
|
||||
|
||||
p.setRenderHint(p.Antialiasing, False)
|
||||
p.setRenderHint(p.TextAntialiasing, True)
|
||||
|
||||
prof = debug.Profiler("AxisItem.paint", disabled=True)
|
||||
p.setPen(self.pen)
|
||||
|
||||
|
@ -27,6 +27,8 @@ class PlotCurveItem(GraphicsObject):
|
||||
self.clear()
|
||||
self.path = None
|
||||
self.fillPath = None
|
||||
self.exportOpts = False
|
||||
self.antialias = False
|
||||
|
||||
if y is not None:
|
||||
self.updateData(y, x)
|
||||
@ -364,6 +366,14 @@ class PlotCurveItem(GraphicsObject):
|
||||
#pen.setColor(c)
|
||||
##pen.setCosmetic(True)
|
||||
|
||||
if self.exportOpts is not False:
|
||||
aa = self.exportOpts['antialias']
|
||||
else:
|
||||
aa = self.antialias
|
||||
|
||||
p.setRenderHint(p.Antialiasing, aa)
|
||||
|
||||
|
||||
if sp is not None:
|
||||
p.setPen(sp)
|
||||
p.drawPath(path)
|
||||
@ -410,7 +420,13 @@ 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."""
|
||||
|
@ -64,6 +64,20 @@ class PlotItem(GraphicsWidget):
|
||||
managers = {}
|
||||
|
||||
def __init__(self, parent=None, name=None, labels=None, title=None, **kargs):
|
||||
"""
|
||||
Create a new PlotItem. All arguments are optional.
|
||||
Any extra keyword arguments are passed to PlotItem.plot().
|
||||
|
||||
Arguments:
|
||||
*title* - Title to display at the top of the item. Html is allowed.
|
||||
*labels* - A dictionary specifying the axis labels to display.
|
||||
{'left': (args), 'bottom': (args), ...}
|
||||
The name of each axis and the corresponding arguments are passed to PlotItem.setLabel()
|
||||
Optionally, PlotItem my also be initialized with the keyword arguments left,
|
||||
right, top, or bottom to achieve the same effect.
|
||||
*name* - Registers a name for this view so that others may link to it
|
||||
"""
|
||||
|
||||
GraphicsWidget.__init__(self, parent)
|
||||
|
||||
self.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
||||
@ -250,12 +264,16 @@ class PlotItem(GraphicsWidget):
|
||||
|
||||
#if name is not None:
|
||||
#self.registerPlot(name)
|
||||
|
||||
if labels is not None:
|
||||
for k in labels:
|
||||
if isinstance(labels[k], basestring):
|
||||
labels[k] = (labels[k],)
|
||||
self.setLabel(k, *labels[k])
|
||||
if labels is None:
|
||||
labels = {}
|
||||
for label in self.scales.keys():
|
||||
if label in kargs:
|
||||
labels[label] = kargs[label]
|
||||
del kargs[label]
|
||||
for k in labels:
|
||||
if isinstance(labels[k], basestring):
|
||||
labels[k] = (labels[k],)
|
||||
self.setLabel(k, *labels[k])
|
||||
|
||||
if title is not None:
|
||||
self.setTitle(title)
|
||||
@ -263,7 +281,7 @@ class PlotItem(GraphicsWidget):
|
||||
if len(kargs) > 0:
|
||||
self.plot(**kargs)
|
||||
|
||||
self.enableAutoRange()
|
||||
#self.enableAutoRange()
|
||||
|
||||
def implements(self, interface=None):
|
||||
return interface in ['ViewBoxWrapper']
|
||||
@ -365,6 +383,8 @@ class PlotItem(GraphicsWidget):
|
||||
#print " Referrers are:", refs
|
||||
#raise
|
||||
|
||||
|
||||
|
||||
def updateGrid(self, *args):
|
||||
g = self.ctrl.gridGroup.isChecked()
|
||||
if g:
|
||||
@ -1313,18 +1333,24 @@ class PlotItem(GraphicsWidget):
|
||||
|
||||
return c
|
||||
|
||||
def saveSvgClicked(self):
|
||||
self.writeSvg()
|
||||
#def saveSvgClicked(self):
|
||||
#self.writeSvg()
|
||||
|
||||
def saveSvgCurvesClicked(self):
|
||||
self.writeSvgCurves()
|
||||
#def saveSvgCurvesClicked(self):
|
||||
#self.writeSvgCurves()
|
||||
|
||||
def saveImgClicked(self):
|
||||
self.writeImage()
|
||||
#def saveImgClicked(self):
|
||||
#self.writeImage()
|
||||
|
||||
def saveCsvClicked(self):
|
||||
self.writeCsv()
|
||||
#def saveCsvClicked(self):
|
||||
#self.writeCsv()
|
||||
|
||||
def setExportMode(self, export, opts):
|
||||
if export:
|
||||
self.autoBtn.hide()
|
||||
else:
|
||||
self.autoBtn.show()
|
||||
|
||||
|
||||
#class PlotWidgetManager(QtCore.QObject):
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
# Form implementation generated from reading ui file 'axisCtrlTemplate.ui'
|
||||
#
|
||||
# Created: Fri Jan 20 12:41:24 2012
|
||||
# by: PyQt4 UI code generator 4.8.3
|
||||
# Created: Thu Mar 22 13:13:14 2012
|
||||
# by: PyQt4 UI code generator 4.8.5
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
@ -19,41 +19,51 @@ class Ui_Form(object):
|
||||
Form.setObjectName(_fromUtf8("Form"))
|
||||
Form.resize(182, 120)
|
||||
Form.setMaximumSize(QtCore.QSize(200, 16777215))
|
||||
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.gridLayout = QtGui.QGridLayout(Form)
|
||||
self.gridLayout.setSpacing(0)
|
||||
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||
self.mouseCheck = QtGui.QCheckBox(Form)
|
||||
self.mouseCheck.setText(QtGui.QApplication.translate("Form", "Mouse Enabled", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.mouseCheck.setChecked(True)
|
||||
self.mouseCheck.setObjectName(_fromUtf8("mouseCheck"))
|
||||
self.gridLayout.addWidget(self.mouseCheck, 0, 1, 1, 2)
|
||||
self.manualRadio = QtGui.QRadioButton(Form)
|
||||
self.manualRadio.setText(QtGui.QApplication.translate("Form", "Manual", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.manualRadio.setObjectName(_fromUtf8("manualRadio"))
|
||||
self.gridLayout.addWidget(self.manualRadio, 1, 0, 1, 1)
|
||||
self.minText = QtGui.QLineEdit(Form)
|
||||
self.minText.setText(QtGui.QApplication.translate("Form", "0", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.minText.setObjectName(_fromUtf8("minText"))
|
||||
self.gridLayout.addWidget(self.minText, 1, 1, 1, 1)
|
||||
self.maxText = QtGui.QLineEdit(Form)
|
||||
self.maxText.setText(QtGui.QApplication.translate("Form", "0", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.maxText.setObjectName(_fromUtf8("maxText"))
|
||||
self.gridLayout.addWidget(self.maxText, 1, 2, 1, 1)
|
||||
self.autoRadio = QtGui.QRadioButton(Form)
|
||||
self.autoRadio.setText(QtGui.QApplication.translate("Form", "Auto", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.autoRadio.setChecked(True)
|
||||
self.autoRadio.setObjectName(_fromUtf8("autoRadio"))
|
||||
self.gridLayout.addWidget(self.autoRadio, 2, 0, 1, 1)
|
||||
self.autoPercentSpin = QtGui.QSpinBox(Form)
|
||||
self.autoPercentSpin.setEnabled(True)
|
||||
self.autoPercentSpin.setSuffix(QtGui.QApplication.translate("Form", "%", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.autoPercentSpin.setMinimum(1)
|
||||
self.autoPercentSpin.setMaximum(100)
|
||||
self.autoPercentSpin.setSingleStep(1)
|
||||
self.autoPercentSpin.setProperty(_fromUtf8("value"), 100)
|
||||
self.autoPercentSpin.setProperty("value", 100)
|
||||
self.autoPercentSpin.setObjectName(_fromUtf8("autoPercentSpin"))
|
||||
self.gridLayout.addWidget(self.autoPercentSpin, 2, 1, 1, 2)
|
||||
self.autoPanCheck = QtGui.QCheckBox(Form)
|
||||
self.autoPanCheck.setText(QtGui.QApplication.translate("Form", "Auto Pan Only", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.autoPanCheck.setObjectName(_fromUtf8("autoPanCheck"))
|
||||
self.gridLayout.addWidget(self.autoPanCheck, 3, 1, 1, 2)
|
||||
self.linkCombo = QtGui.QComboBox(Form)
|
||||
self.linkCombo.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
|
||||
self.linkCombo.setObjectName(_fromUtf8("linkCombo"))
|
||||
self.gridLayout.addWidget(self.linkCombo, 4, 1, 1, 2)
|
||||
self.label = QtGui.QLabel(Form)
|
||||
self.label.setText(QtGui.QApplication.translate("Form", "Link Axis:", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.label.setObjectName(_fromUtf8("label"))
|
||||
self.gridLayout.addWidget(self.label, 4, 0, 1, 1)
|
||||
|
||||
@ -61,13 +71,5 @@ class Ui_Form(object):
|
||||
QtCore.QMetaObject.connectSlotsByName(Form)
|
||||
|
||||
def retranslateUi(self, Form):
|
||||
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.mouseCheck.setText(QtGui.QApplication.translate("Form", "Mouse Enabled", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.manualRadio.setText(QtGui.QApplication.translate("Form", "Manual", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.minText.setText(QtGui.QApplication.translate("Form", "0", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.maxText.setText(QtGui.QApplication.translate("Form", "0", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.autoRadio.setText(QtGui.QApplication.translate("Form", "Auto", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.autoPercentSpin.setSuffix(QtGui.QApplication.translate("Form", "%", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.autoPanCheck.setText(QtGui.QApplication.translate("Form", "Auto Pan Only", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.label.setText(QtGui.QApplication.translate("Form", "Link Axis:", None, QtGui.QApplication.UnicodeUTF8))
|
||||
pass
|
||||
|
||||
|
@ -94,7 +94,11 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="linkCombo"/>
|
||||
<widget class="QComboBox" name="linkCombo">
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
|
Loading…
Reference in New Issue
Block a user