由于你没有解释变焦的要求(见我的评论),我不会在这个答案中实现这一部分。
QtCharts中滚动的一般逻辑是设置轴的最小和最大属性,而这些最小和最大属性取决于QXSerie和QXAxis的类型,例如,如果它是一个带有QValueAxis的QLineSeries,它们所取的值可以是所有真实的,但如果它是一个带有QCategoryAxis的QCandlestickSeries,它们只取类别名称。
假设你使用的逻辑与我之前的回答相同,那么类别对应于一串整数值,这些整数值是QLineSeries显示的值,所以当你计算极限时,你应该采用这个参考。
另一方面,在QtCharts中没有get_xlim,所以你必须手动计算它,考虑到这种情况,它与数据的数量相符。
from PyQt5 import QtCore, QtGui, QtWidgets, QtChart
import math
import numpy as np
import pandas as pd
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.step = 0.1
self._chart_view = QtChart.QChartView()
self.scrollbar = QtWidgets.QScrollBar(
QtCore.Qt.Horizontal,
sliderMoved=self.onAxisSliderMoved,
pageStep=self.step * 100,
self.slider = QtWidgets.QSlider(
QtCore.Qt.Horizontal, sliderMoved=self.onZoomSliderMoved
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
lay = QtWidgets.QVBoxLayout(central_widget)
for w in (self._chart_view, self.scrollbar, self.slider):
lay.addWidget(w)
self.resize(640, 480)
self._chart = QtChart.QChart()
self._candlestick_serie = QtChart.QCandlestickSeries()
self._line_serie = QtChart.QLineSeries()
tm = []
df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv"
name_of_columns = ("AAPL.Open", "AAPL.High", "AAPL.Low", "AAPL.Close", "mavg")
for i, (o, h, l, c, v) in enumerate(
zip(*(df[name] for name in name_of_columns))
self._candlestick_serie.append(QtChart.QCandlestickSet(o, h, l, c))
self._line_serie.append(QtCore.QPointF(i, v))
tm.append(str(i))
min_x, max_x = 0, i
self._chart.addSeries(self._candlestick_serie)
self._chart.addSeries(self._line_serie)
self._chart.createDefaultAxes()
self._chart.legend().hide()
# self._chart.setAnimationOptions(QtChart.QChart.SeriesAnimations)
self._chart.axisX(self._candlestick_serie).setCategories(tm)
self._chart.axisX(self._candlestick_serie).setVisible(False)
self._chart_view.setChart(self._chart)
self.adjust_axes(100, 200)
self.lims = np.array([min_x, max_x])
self.onAxisSliderMoved(self.scrollbar.value())
def adjust_axes(self, value_min, value_max):
self._chart.axisX(self._candlestick_serie).setRange(
str(value_min), str(value_max)
self._chart.axisX(self._line_serie).setRange(value_min, value_max)
@QtCore.pyqtSlot(int)
def onAxisSliderMoved(self, value):
r = value / ((1 + self.step) * 100)
l1 = self.lims[0] + r * np.diff(self.lims)
l2 = l1 + np.diff(self.lims) * self.step
self.adjust_axes(math.floor(l1), math.ceil(l2))
@QtCore.pyqtSlot(int)
def onZoomSliderMoved(self, value):
print(value)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self._chart_view = QtChart.QChartView()
self.scrollbar = QtWidgets.QScrollBar(
QtCore.Qt.Horizontal, sliderMoved=self.recalculate_range, pageStep=10
self.slider = QtWidgets.QSlider(
QtCore.Qt.Horizontal,
sliderMoved=self.recalculate_range,
minimum=0,
maximum=100,
value=60,
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
lay = QtWidgets.QVBoxLayout(central_widget)
for w in (self._chart_view, self.scrollbar, self.slider):
lay.addWidget(w)
self.resize(640, 480)
self._chart = QtChart.QChart()
self._line_serie = QtChart.QLineSeries(name="Data")
x = pd.read_csv(
"file.txt", index_col="DATE", parse_dates=True, infer_datetime_format=True
self._z = x.iloc[:, 3].values
N = len(self._z)
for i, v in enumerate(self._z):
self._line_serie.append(QtCore.QPointF(i, v))
self.lims = 0, N
self._chart.addSeries(self._line_serie)
self._chart.createDefaultAxes()
# self._chart.legend().hide()
# self._chart.setAnimationOptions(QtChart.QChart.SeriesAnimations)
self._chart_view.setChart(self._chart)
self.recalculate_range()
def recalculate_range(self):
m, M = self.lims
step = self.slider.sliderPosition() / 100.0
r = self.scrollbar.value() / ((1 + step) * 100.0)
xmin = m + r * np.diff(self.lims)
xmax = xmin + np.diff(self.lims) * step
self._chart.axisX(self._line_serie).setRange(xmin, xmax)
if xmin > 0 and xmax > 0 and xmax < M:
ymin = np.amin(self._z[int(xmin) : int(xmax)])
ymax = np.amax(self._z[int(xmin) : int(xmax)])
self._chart.axisY(self._line_serie).setRange(ymin, ymax)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())