如何显式设置QChart轴刻度?

10

使用缩放线示例,我创建了一个Python QChartView类,可以使用箭头键滚动并使用加号和减号键进行缩放(请参阅下面的我的代码)。

当我向左滚动时,我希望网格线和轴刻度与数据一起滚动。然而,只有数据(QLineSeries)向左滚动。5个网格线仍然保持在相同的位置,但其刻度值已更新。这是不可取的,因为新的刻度值可能是任何值。

我在文档中查找过,但没有找到如何使网格与数据一起滚动。我错过了什么吗?

我还想能够将刻度设置为显式值(以便我可以自己实现滚动行为)。是否可以将轴刻度值设置为特定值?

我的示例代码:

import sys
from math import pi, sin, sqrt

from PyQt5.QtChart import QLineSeries, QChart, QChartView
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication

class ZoomPanChartView(QChartView):
    """ QChartView that can zoom/pan with the keys
    """
    def __init__(self, chart):
        super().__init__(chart)

        self.zoomFactor = sqrt(2) # QCharts default is 2
        self.panPixels = 10

    def keyPressEvent(self, keyEvent):
        """ Panning (scrolling) is done with the arrow keys. 
            Zooming goes with the plus and minus keys.
            The '=' key resets.
        """
        key = keyEvent.key()

        if key == Qt.Key_Equal:
            self.chart().zoomReset()
        if key == Qt.Key_Plus:
            self.chart().zoom(self.zoomFactor)
        elif key == Qt.Key_Minus:
            self.chart().zoom(1/self.zoomFactor)
        elif key == Qt.Key_Left:
            self.chart().scroll(-self.panPixels, 0)
        elif key == Qt.Key_Right:
            self.chart().scroll(+self.panPixels, 0)
        elif key == Qt.Key_Up:
            self.chart().scroll(0, +self.panPixels)
        elif key == Qt.Key_Down:
            self.chart().scroll(0, -self.panPixels)
        elif key == Qt.Key_0:
            self.chart().axisX().applyNiceNumbers() # changes the range
        else:
            super().keyPressEvent(keyEvent)


def main():
    app = QApplication(sys.argv)
    chart = QChart()

    series = QLineSeries()
    for i in range(0, 100):
        x = i * pi / 20
        y = sin(x)
        series.append(x, y)

    chart.addSeries(series)
    chart.createDefaultAxes()
    chart.axisY().setRange(-1, 1)
    chart.legend().hide()

    chartView = ZoomPanChartView(chart)
    chartView.show()
    chartView.resize(400, 300)
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()    

我遇到了同样的问题。为了使网格易于阅读,我希望网格步长可以独立于滚动和平移设置并固定。因此,我也想自己设置网格刻度值。这样,当您移动时,它会随之移动。QChart的网格根本不易于阅读。我会尝试一些方法,并在这里说出其中一个是否有效。 - A. Vieira
3个回答

5
你可以使用 QCategoryAxis 将刻度线放置在你想要的位置:
初始化:
ch = self.chView.chart()
self.chartAxisX = QCategoryAxis(labelsPosition=QCategoryAxis.AxisLabelsPositionOnValue, startValue=0.0)
ch.setAxisX(self.chartAxisX)
self.chartAxisY = QCategoryAxis(labelsPosition=QCategoryAxis.AxisLabelsPositionOnValue, startValue=0.0)
ch.setAxisY(self.chartAxisY)

添加系列:

        ch.addSeries(s)
        s.attachAxis(self.chartAxisX)
        s.attachAxis(self.chartAxisY)

在5的倍数处设置刻度:

        for s in self.chartAxisX.categoriesLabels():
            self.chartAxisX.remove(s)
        for i in range(0, int(max_x_value) + 1, 5):
            self.chartAxisX.append(str(i), i)
        self.chartAxisX.setRange(0.0, max_x_value)

或者使用这个通用函数适用于任何间隔:

def format_axis(axis, min_value, max_value, step):
    for s in axis.categoriesLabels():
        axis.remove(s)
    axis.setStartValue(min_value)
    for i in range(ceil(min_value / step), floor(max_value / step) + 1):
        v = i * step
        axis.append('%g' % v, v)
    axis.setRange(min_value, max_value)

format_axis(self.chartAxisX, -1.1, 0.98, 0.25)

感谢您的回答。与此同时,我已决定使用PyQtGraph,但是谁知道,在未来的项目中我可能会使用QtCharts。 - titusjan

1
我找到的最好方法是在QChart上将一个QValueAxis设置为坐标轴,并调用QValueAxis::applyNiceNumbers()来调整范围,即当前比例尺的最大值和最小值,以使显示的数字更易读。但这会改变数据的位置而不是网格线的位置。您可以在水平条形图示例中检查函数的行为。
我考虑使用QLineSeries数据集自己制作网格,但我需要改变轴上刻度的位置,而根据我所能确定的,使用当前的QChart难以实现。
简短回答:您无法使用QCharts实现此目的。

我已经使用Qwt库有一段时间了,可以证明那里的网格表现符合预期,其他行为也更加成熟。平移可以移动网格,缩放可以使网格按步骤调整大小以保持易读性。也许值得一试。


1

我认为您可以使用 QCharts 和 QValueAxis 来完成此操作:

  QValueAxis *axisY = new QValueAxis;
  axisY->setTickType(QValueAxis::TicksDynamic);
  axisY->setTickAnchor(0.0);
  axisY->setTickInterval(0.2);

请参考优秀的标签算法,了解如何确定合适的刻度间隔。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接