PyQtGraph:如何计算ViewBox内角度以实现曲线文本对齐
解决PyQtGraph中文本与曲线对齐的角度计算问题
想要让文本项根据曲线前两个数据点的角度对齐,实现类似算盘的样式,但直接通过数据坐标计算的角度无法匹配ViewBox的显示刻度,导致文本未正确对齐。
核心原因
直接用数据点的y/x比值计算的是数据空间的斜率,但PyQtGraph的TextItem.angle参数使用的是屏幕空间的角度(以度为单位,顺时针为正)。两者因ViewBox的缩放比例不同,无法直接对应。
解决方案
将数据点转换为屏幕像素坐标,基于像素差值计算实际显示角度,步骤如下:
- 获取PlotWidget的ViewBox实例
- 将目标数据点转换为屏幕像素坐标
- 根据像素坐标的差值计算屏幕角度(注意屏幕y轴向下的特性)
修改后的完整代码
import pyqtgraph as pg import numpy as np from PyQt5 import QtCore from PyQt5.QtGui import QFont # plot widget pw = pg.plot(title="How to align the text item with the curves ?", pen="b") def abacus( pw, # a plot widget item x, ys, # same x for all ys curves labels, # text to display on each curve indx_txt=0, # index used to compute text angle and position width=2, color=(140, 140, 140, 140), fontsize=12 ): # to store and return created items lines = [] viewbox = pw.getViewBox() # 获取ViewBox实例 for y, lab in zip(ys, labels): line = pw.plot( x, y, pen=pg.mkPen(color=color, width=width, style=QtCore.Qt.DashLine), width=width, name=lab, ) # 将数据点转换为屏幕像素坐标 p1 = viewbox.mapToDevice(QtCore.QPointF(x[indx_txt], y[indx_txt])) p2 = viewbox.mapToDevice(QtCore.QPointF(x[indx_txt+1], y[indx_txt+1])) # 计算屏幕坐标的差值,注意屏幕y轴向下,dy取反 dx = p2.x() - p1.x() dy = p2.y() - p1.y() # 计算屏幕角度(转换为度,TextItem使用顺时针角度) angle = np.degrees(np.arctan2(-dy, dx)) txt = pg.TextItem( text=lab, color=color, anchor=(0, 0.9), border=None, angle=angle, # 使用转换后的屏幕角度 ) font = QFont() font.setPixelSize(fontsize) txt.setFont(font) pw.addItem(txt) txt.setPos(x[indx_txt], y[indx_txt]) lines.append((line, txt)) return lines # create dummy data and labels x = np.arange(5, 8) ys = 2*(3*(x+3)+np.outer(x, x)) labs = [f"This is the {i} curve" for i in range(3)] lines = abacus(pw, x, ys, labs) pg.exec()
关键细节说明
viewbox.mapToDevice():将数据坐标系的点转换为屏幕像素坐标,消除ViewBox缩放的影响np.arctan2(-dy, dx):屏幕y轴方向与常规数学坐标系相反,因此对dy取反,确保角度计算符合屏幕显示逻辑np.degrees():将弧度转换为度,匹配TextItem.angle的参数要求
内容的提问来源于stack exchange,提问作者mocquin
相关产品推荐
相关产品推荐

