在3D图中绘制无法缩放或移动的文本

问题描述

你好Pyqtgraph社区,

我希望能够在PyQtGraph中生成的3D交互式绘图中创建“固定”文本窗口。 该文本窗口将包含与仿真有关的信息,并且无论您放大/缩小还是向左或向右平移,该窗口始终始终可见。并且窗口的位置不应更改。

到目前为止,我找到的所有解决方案均创建一个文本对象,该对象随轴的缩放比例变化而移动。例如,下面的代码在3D轴上打印文本,但是一旦放大/缩小,文本就会在整个位置移动。任何想法将不胜感激。

预先感谢

from pyqtgraph.Qt import QtCore,QtGui
import pyqtgraph.opengl as gl
from pyqtgraph.opengl.GLGraphicsItem import GLGraphicsItem

class GLTextItem(GLGraphicsItem):
    """
    Class for plotting text on a GLWidget
    """

    def __init__(self,X=None,Y=None,Z=None,text=None):
        GLGraphicsItem.__init__(self)
        self.setGLOptions('translucent')
        self.text = text
        self.X = X
        self.Y = Y
        self.Z = Z

    def setGLViewWidget(self,GLViewWidget):
        self.GLViewWidget = GLViewWidget

    def setText(self,text):
        self.text = text
        self.update()

    def setX(self,X):
        self.X = X
        self.update()

    def setY(self,Y):
        self.Y = Y
        self.update()

    def setZ(self,Z):
        self.Z = Z
        self.update()

    def paint(self):
        self.GLViewWidget.qglColor(QtCore.Qt.white)
        self.GLViewWidget.renderText(self.X,self.Y,self.Z,self.text)


if __name__ == '__main__':
    # Create app
    app = QtGui.QApplication([])
    w1 = gl.GLViewWidget()
    w1.resize(800,800)
    w1.show()
    w1.setwindowTitle('Earth 3D')

    gl_txt = GLTextItem(10,10,'Sample test')
    gl_txt.setGLViewWidget(w1)
    w1.addItem(gl_txt)

    while w1.isVisible():
        app.processEvents()

解决方法

所以我终于找到了解决方案。需要做的是:

  1. 继承 GLViewWidget
  2. 从派生类中重载paintGL(),以便每次调用paigGL() 时,它都使用成员函数renderText() 在屏幕上渲染文本。

renderText() 被重载以支持绝对屏幕坐标以及基于轴的坐标: i) renderText(int x,int y,const QString &str,const QFont &font = QFont()): 基于 (x,y) 窗口坐标绘制 ii) renderText(double x,double y,double z,const QFont &font = QFont()): 在 (x,y,z) 场景坐标上绘图

您可能想要使用 QtGui.QFontMetrics() 类来获取渲染文本的尺寸,以便将其放置在对您的应用程序有意义的位置,如下面的代码所示。

from pyqtgraph.opengl import GLViewWidget
import pyqtgraph.opengl as gl
from PyQt5.QtGui import QColor
from pyqtgraph.Qt import QtCore,QtGui


class GLView(GLViewWidget):
    """
    I have implemented my own GLViewWidget
    """
    def __init__(self,parent=None):
        super().__init__(parent)

    def paintGL(self,*args,**kwds):
        # Call parent's paintGL()
        GLViewWidget.paintGL(self,**kwds)

        # select font
        font = QtGui.QFont()
        font.setFamily("Tahoma")
        font.setPixelSize(21)
        font.setBold(True)

        title_str = 'Screen Coordinates'
        metrics = QtGui.QFontMetrics(font)
        m = metrics.boundingRect(title_str)
        width = m.width()
        height = m.height()

        # Get window dimensions to center text
        scrn_sz_width = self.size().width()
        scrn_sz_height = self.size().height()

        # Render text with screen based coordinates
        self.qglColor(QColor(255,255,255))
        self.renderText((scrn_sz_width-width)/2,height+5,title_str,font)

        # Render text using Axis-based coordinates
        self.qglColor(QColor(255,255))
        self.renderText(0,'Axis-Based Coordinates')


if __name__ == '__main__':
    # Create app
    app = QtGui.QApplication([])
    w = GLView()
    w.resize(800,800)
    w.show()
    w.setWindowTitle('Earth 3D')
    w.setCameraPosition(distance=20)
    g = gl.GLGridItem()
    w.addItem(g)

    while w.isVisible():
        app.processEvents()