在不缩放或移动的 3d 图中绘制文本

Posted

技术标签:

【中文标题】在不缩放或移动的 3d 图中绘制文本【英文标题】:Plot text in 3d-plot that does not scale or move 【发布时间】:2021-02-12 11:23:38 【问题描述】:

你好 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, 10, 'Sample test')
    gl_txt.setGLViewWidget(w1)
    w1.addItem(gl_txt)

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

【问题讨论】:

【参考方案1】:

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

    子类化 GLViewWidget 从派生类中重载paintGL(),以便每次调用paingGL() 时它都使用成员函数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 QString &str, 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, *args, **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,0,255))
        self.renderText((scrn_sz_width-width)/2, height+5, title_str, font)

        # Render text using Axis-based coordinates
        self.qglColor(QColor(255, 0, 0, 255))
        self.renderText(0, 0, 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()

【讨论】:

以上是关于在不缩放或移动的 3d 图中绘制文本的主要内容,如果未能解决你的问题,请参考以下文章

在 Matlab 中缩放散点图中的文本

Unity3D 控制物体移动旋转缩放

缩放图像后触摸移动事件不会触发(scale3d)

在不移动叠加视图的情况下裁剪和缩放图像,而是在 ImageView 中移动图像

在不删除数据的情况下限制 ggplot2 轴(超出限制):缩放

使用python中的对数轴缩放和拟合对数正态分布