Source code for pyqtgraph.opengl.items.GLTextItem

import numpy as np

from ... import functions as fn
from ...Qt import QtCore, QtGui
from ..GLGraphicsItem import GLGraphicsItem

__all__ = ['GLTextItem']

[docs] class GLTextItem(GLGraphicsItem): """Draws text in 3D."""
[docs] def __init__(self, parentItem=None, **kwds): """All keyword arguments are passed to setData()""" super().__init__(parentItem=parentItem) glopts = kwds.pop('glOptions', 'additive') self.setGLOptions(glopts) self.items = [] self.pos = [0.0, 0.0, 0.0] self.color = QtGui.QColor(QtCore.Qt.GlobalColor.white) self.text = '' self.font = QtGui.QFont('Helvetica', 16) self.alignment = QtCore.Qt.AlignmentFlag.AlignLeft | QtCore.Qt.AlignmentFlag.AlignBottom self.setData(**kwds)
[docs] def setData(self, **kwds): """ Update the data displayed by this item. All arguments are optional; for example it is allowed to update text while leaving colors unchanged, etc. ==================== ================================================== **Arguments:** ------------------------------------------------------------------------ pos (3,) array of floats specifying text location. text String to display. color QColor or array of ints [R,G,B] or [R,G,B,A]. (Default: Qt.white) font QFont (Default: QFont('Helvetica', 16)) alignment QtCore.Qt.AlignmentFlag (Default: QtCore.Qt.AlignmentFlag.AlignLeft | QtCore.Qt.AlignmentFlag.AlignBottom) items Optional list of dicts. Each dict specifies parameters for a single textitem: {'pos', 'text', 'color', 'font', 'alignment'}. This allows rendering multiple text items. 'pos' and 'text' are required keys, the rest are optional. ==================== ================================================== """ args = ['pos', 'text', 'color', 'font', 'alignment', 'items'] for k in kwds.keys(): if k not in args: raise ValueError('Invalid keyword argument: %s (allowed arguments are %s)' % (k, str(args))) for arg in args: if arg in kwds: value = kwds[arg] if arg == 'pos': if isinstance(value, np.ndarray): if value.shape != (3,): raise ValueError('"pos.shape" must be (3,).') elif isinstance(value, (tuple, list)): if len(value) != 3: raise ValueError('"len(pos)" must be 3.') elif arg == 'color': value = fn.mkColor(value) elif arg == 'font': if isinstance(value, QtGui.QFont) is False: raise TypeError('"font" must be QFont.') elif arg == 'items': if not isinstance(value, list): raise ValueError('"items" must be list of dicts') setattr(self, arg, value) self.update()
def paint(self): items = [dict(text=self.text, pos=self.pos)] if len(self.text) != 0 else self.items if len(items) == 0: return self.setupGLState() device = self.view() rect = QtCore.QRectF(0, 0, device.width(), device.height()) project = self.compute_projection(rect) painter = QtGui.QPainter(device) painter.setRenderHints(QtGui.QPainter.RenderHint.Antialiasing | QtGui.QPainter.RenderHint.TextAntialiasing) for item in items: # text and pos must be specified text = item['text'] pos = item['pos'] if len(text) == 0: continue # alignment, color, font fallback to defaults alignment = item.get('alignment', self.alignment) color = item.get('color') color = fn.mkColor(color) if color is not None else self.color font = item.get('font', self.font) vec3 = QtGui.QVector3D(*pos) pos_2d = self.align_text(project.map(vec3).toPointF(), text, font, alignment) painter.setPen(color) painter.setFont(font) painter.drawText(pos_2d, text) painter.end() def compute_projection(self, rect : QtCore.QRectF): # note that QRectF.bottom() != QRect.bottom() ndc_to_viewport = QtGui.QMatrix4x4() ndc_to_viewport.viewport(rect.left(), rect.bottom(), rect.width(), -rect.height()) return ndc_to_viewport * self.mvpMatrix()
[docs] def align_text(self, pos, text, font, alignment): """ Aligns the text at the given position according to the given alignment. """ font_metrics = QtGui.QFontMetrics(font) rect = font_metrics.tightBoundingRect(text) width = rect.width() height = rect.height() dx = dy = 0.0 if alignment & QtCore.Qt.AlignmentFlag.AlignRight: dx = width if alignment & QtCore.Qt.AlignmentFlag.AlignHCenter: dx = width / 2.0 if alignment & QtCore.Qt.AlignmentFlag.AlignTop: dy = height if alignment & QtCore.Qt.AlignmentFlag.AlignVCenter: dy = height / 2.0 return QtCore.QPointF(pos.x() - dx, pos.y() + dy)