PySide6多Y轴QChart下Callout提示位置偏移问题求助
多Y轴场景下QChart Callout提示偏移修复方案
偏移的核心原因是QChart.mapToPosition方法默认使用图表的默认轴做坐标转换,多Y轴场景下不同序列绑定的Y轴范围、对齐方式都不同,必须指定对应序列才能计算出正确的屏幕坐标。以下是具体修改步骤:
1. 修改Callout类
新增序列存储属性,所有坐标转换逻辑都指定对应序列:
class Callout(QGraphicsItem): def __init__(self, chart): QGraphicsItem.__init__(self, chart) self.chart = chart self._text = "" self._textRect = QRectF() self._anchor = QPointF() self._font = QFont() self._rect = QRectF() # 新增:存储当前提示对应的序列 self._series = None # 新增:设置对应序列的方法 def set_series(self, series): self._series = series def boundingRect(self): # 修改:坐标转换传入对应序列 anchor = self.mapFromParent(self.chart.mapToPosition(self._anchor, self._series)) rect = QRectF() rect.setLeft(min(self._rect.left(), anchor.x())) rect.setRight(max(self._rect.right(), anchor.x())) rect.setTop(min(self._rect.top(), anchor.y())) rect.setBottom(max(self._rect.bottom(), anchor.y())) return rect def paint(self, painter, option, widget): path = QPainterPath() path.addRoundedRect(self._rect, 5, 5) # 修改:坐标转换传入对应序列 anchor = self.mapFromParent(self.chart.mapToPosition(self._anchor, self._series)) # 以下原有paint逻辑无需修改 if not self._rect.contains(anchor) and not self._anchor.isNull(): point1 = QPointF() point2 = QPointF() # 确定锚点相对于_rect的位置 above = anchor.y() <= self._rect.top() above_center = (anchor.y() > self._rect.top() and anchor.y() <= self._rect.center().y()) below_center = (anchor.y() > self._rect.center().y() and anchor.y() <= self._rect.bottom()) below = anchor.y() > self._rect.bottom() on_left = anchor.x() <= self._rect.left() left_of_center = (anchor.x() > self._rect.left() and anchor.x() <= self._rect.center().x()) right_of_center = (anchor.x() > self._rect.center().x() and anchor.x() <= self._rect.right()) on_right = anchor.x() > self._rect.right() # 获取最近的_rect边角 x = (on_right + right_of_center) * self._rect.width() y = (below + below_center) * self._rect.height() corner_case = ((above and on_left) or (above and on_right) or (below and on_left) or (below and on_right)) vertical = abs(anchor.x() - x) > abs(anchor.y() - y) x1 = (x + left_of_center * 10 - right_of_center * 20 + corner_case * int(not vertical) * (on_left * 10 - on_right * 20)) y1 = (y + above_center * 10 - below_center * 20 + corner_case * vertical * (above * 10 - below * 20)) point1.setX(x1) point1.setY(y1) x2 = (x + left_of_center * 20 - right_of_center * 10 + corner_case * int(not vertical) * (on_left * 20 - on_right * 10)) y2 = (y + above_center * 20 - below_center * 10 + corner_case * vertical * (above * 20 - below * 10)) point2.setX(x2) point2.setY(y2) path.moveTo(point1) path.lineTo(anchor) path.lineTo(point2) path = path.simplified() painter.setBrush(QColor(255, 255, 255)) painter.drawPath(path) painter.drawText(self._textRect, self._text) def update_geometry(self): self.prepareGeometryChange() # 修改:坐标转换传入对应序列 self.setPos(self.chart.mapToPosition(self._anchor, self._series) + QPointF(10, -50)) # 其余原有方法无需修改,保持不变即可
2. 修改CreateChart类的tooltip方法
悬浮触发时获取当前序列并传递给Callout:
def tooltip(self, point, state): if self._tooltip == 0: self._tooltip = Callout(self.chart) if state: # 新增:获取触发悬浮信号的当前序列 current_series = self.sender() x = point.x() y = point.y() self._tooltip.set_text(f"X: {x:.1f} \nY: {y:.1f} ") self._tooltip.set_anchor(point) # 新增:给Callout设置当前序列 self._tooltip.set_series(current_series) self._tooltip.setZValue(11) self._tooltip.update_geometry() self._tooltip.show() else: self._tooltip.hide()
修改完成后所有序列的Callout都会匹配自身绑定的Y轴计算坐标,偏移问题即可解决。
内容的提问来源于stack exchange,提问作者Jakob
相关产品推荐
相关产品推荐

