How to check the QChart axis checkbox explicitly?

Usage Example of a scaling line I created a Python QChartView class that can be scrolled with the arrow keys and enlarged with the plus and minus keys. (see my code below).

When I scroll left, I expect the grid lines and ticks of the axis to scroll the same amount as the data. However, only data (QLineSeries) scrolls to the left. 5 grid lines remain at the same positions, but their check values ​​are updated. This is undesirable since new tick values ​​can be anything.

I looked through the documentation, but could not find how to make the grid scroll along with the data. Did I miss something?

I would also like to set ticks to explicit values ​​(so that I can possibly implement scroll behavior). Can I set axis tick values ​​for specific values?

My sample code is:

 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() 
+5
source share
2 answers

The best I could find was to set QValueAxis as the axis on QChart and call QValueAxis::applyNiceNumbers() to adjust the range, i.e. max and min of the current scale, so the numbers shown are a little more readable for humans. But this will change the position of the data instead of the positions of the grid lines. You can check the behavior of the function on horizontalBarChart .

I thought about using the QLineSeries dataset to make the grid myself, but I would need to change the position of the tick on the axis, which, as far as I could tell, is not easy to do with the current QChart.

Short answer: you cannot do this with QCharts.

I have been working with the Qwt library for some time, and I can confirm that the grid there behaves as expected, and other behaviors are also a bit more mature. Panning moves the capture, while zooming makes the grid resize in steps to remain human readable. Perhaps worth checking out.

+1
source

You can use QCategoryAxis to place ticks where you want:

Initialize:

 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) 

add series:

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

sets ticks with a multiple of 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) 

or use this generic function for any interval:

 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) 
+1
source

Source: https://habr.com/ru/post/1265882/


All Articles