QScrollArea, скролл графика
Есть график, довольно большой по оси X. Надо отображать в окошке только его часть, остальное должно быть прокручиваемой ползунком в QScrollArea.
from PySide6.QtWidgets import *
from PySide6.QtGui import *
from PySide6.QtCore import *
from PySide6.QtCharts import *
import pandas as pd
import sys
# Функция чтения данных
def read_csv_file( file, n):
df = pd.read_csv(file)
col = df.loc[:, n]
return col.tolist()
# Скролл обёртка для графика
class ScrollChartClass(QWidget):
def __init__(self, chart):
super().__init__()
self.chart = chart
self.initUI()
def initUI(self):
self.scroll = QScrollArea()
self.hbox = QHBoxLayout()
self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.scroll.setWidgetResizable(True)
self.scroll.sizePolicy()
self.scroll.setWidget(self.chart)
self.hbox.addWidget(self.scroll)
self.setLayout(self.hbox)
return
class Main(QWidget):
def __init__(self, parent: QObject = None):
super().__init__(parent)
self.filename = "example_csv_file.csv"
self.resize(1000, 250)
self.initUI()
def initUI(self):
# достали данные
self.data1_1 = read_csv_file(self.filename, 'plan_mes')
self.data1_2 = read_csv_file(self.filename, 'plan_prj')
seriesData1_1 = QLineSeries()
seriesData1_2 = QLineSeries()
# одинаковое число строк в файле => для всех графиков одинаковая длина OX
for x in range(len(self.data1_1)):
seriesData1_1.append(QPointF(x, self.data1_1[x]))
seriesData1_1.setColor(QColor("green"))
seriesData1_1.setName('plan_mes')
seriesData1_2.append(QPointF(x, self.data1_2[x]))
seriesData1_2.setColor(QColor("red"))
seriesData1_2.setName('plan_prj')
x_axis = QValueAxis()
x_axis.setRange(0.0, len(self.data1_1))
y_axis = QValueAxis()
y_axis.setRange(min(self.data1_1), max(self.data1_1))
chartModel = QChart()
chartModel.layout().setContentsMargins(0, 0, 0, 0) #
chartModel.addSeries(seriesData1_1)
chartModel.addSeries(seriesData1_2)
chartModel.createDefaultAxes()
windowLayout = QGridLayout() # было бы достаточно QHBoxLayout()
view = QChartView(chartModel)
view.setRenderHint(QPainter.Antialiasing)
scroll_chart_class = ScrollChartClass(view)
windowLayout.addWidget(scroll_chart_class, 0, 0)
self.setLayout(windowLayout)
if __name__ == "__main__":
import sys
app = QApplication()
w = Main()
w.show()
sys.exit(app.exec())
График построен по данным из игрушечного файла, там сейчас 200 строк, т.е. 200 значений по оси X. Сейчас все эти 200 строк отображаются одновременно.
Мне надо видеть, например, 50 из них, остальное должно быть под скроллом.
Первая мысль - покрутить настройки x_axis.setRange, но нет, не получается.
Пример сделан в PySide, это тот же PyQt, пусть никого не смущает.
Ответы (2 шт):
Автор решения: S. Nick
→ Ссылка
PySide6.QtGui.QWindow.setMinimumWidth(w)
содержит минимальную ширину виджета в пикселях.
'''
from PySide6.QtWidgets import *
from PySide6.QtGui import *
from PySide6.QtCore import *
from PySide6.QtCharts import * # PySide6 QtCharts
import pandas as pd
'''
import sys
from PyQt5.Qt import *
from PyQt5.QtChart import * # PyQt5 QtChart
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setWindowTitle("PyQt скролл графика")
self.resize(1100, 500)
self.centralWidget = QWidget()
self.setCentralWidget(self.centralWidget)
self.scroll_area = QScrollArea()
self.scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
# self.scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.scroll_container = QWidget()
self.scroll_area.setWidgetResizable(True)
self.scroll_area.setWidget(self.scroll_container)
self.scroll_layout = QHBoxLayout(self.scroll_container)
self.scroll_layout.setContentsMargins(0, 0, 0, 0)
self.plot_button = QPushButton("Add plot")
self.plot_button.clicked.connect(self.plot)
windowLayout = QVBoxLayout(self.centralWidget)
windowLayout.addWidget(self.scroll_area)
windowLayout.addWidget(self.plot_button)
def plot(self):
container = QWidget() # +++
lay = QVBoxLayout(container) # +++
lay.setContentsMargins(0, 0, 0, 0) # +++
self.scroll_layout.addWidget(container) # +++
container.setMinimumWidth(1000) # !!! +++ <----
x = ['2018-07-01 13:06:38', '2018-07-01 12:46:38',
'2018-07-01 12:36:38', '2018-07-01 12:26:38',
'2018-07-01 12:16:38', '2018-07-01 12:06:38',
'2018-07-01 11:56:38', '2018-07-01 11:46:38',
'2018-07-01 11:36:38', '2018-07-01 11:26:38',
'2018-07-01 10:56:38', '2018-07-01 10:46:38',
'2018-07-01 10:36:38']
y = [23.5, 20.8, 28.0, 28.1, 28.0, 27.8, 27.3, 27.2,
25.7, 24.7, 25.0, 25.0, 24.9]
num_ticks = 10
time_len = 'Time'
series = QLineSeries()
for t, val in zip(x, y):
series.append(QDateTime.fromString(
t, "yyyy-MM-dd hh:mm:ss").toMSecsSinceEpoch(), val)
chart = QChart()
chart.addSeries(series)
font = QFont("Sans Serif", )
font.setPixelSize(18)
chart.setTitleFont(font)
chart.setTitle("Температура в градусах Цельсия для устройства:")
chart.setAnimationOptions(QChart.SeriesAnimations)
palette = QPalette()
palette.setColor(QPalette.Text, Qt.red)
chart.setPalette(palette)
backgroundGradient = QLinearGradient(0, 0, 0, 400)
backgroundGradient.setColorAt(0.0, QColor('#50a1dc'))
backgroundGradient.setColorAt(1.0, QColor('#00a1de'))
chart.setBackgroundBrush(backgroundGradient)
plotAreaGradient = QLinearGradient(0, 100, 0, 400)
plotAreaGradient.setColorAt(0.0, QColor('#f1f1f1'))
plotAreaGradient.setColorAt(1.0, QColor('#ffffff'))
chart.setPlotAreaBackgroundBrush(plotAreaGradient)
chart.setPlotAreaBackgroundVisible(True)
axisX = QDateTimeAxis()
axisX.setTickCount(num_ticks)
axisX.setFormat("dd-MM HH:mm")
axisX.setTitleText(time_len)
axisY = QValueAxis()
axisY.setLabelFormat("%i")
axisY.setTitleText("Temperature C")
Lfont = QFont("Sans Serif")
Lfont.setPixelSize(16)
axisX.setLabelsFont(Lfont)
axisY.setLabelsFont(Lfont)
axisPen = QPen(QColor('#151512'))
axisPen.setWidth(2)
axisX.setLinePen(axisPen)
axisY.setLinePen(axisPen)
axisBrush = QBrush(QColor('#ffffff'))
axisX.setLabelsBrush(axisBrush)
axisY.setLabelsBrush(axisBrush)
axisX.setGridLineVisible(True)
axisY.setGridLineVisible(True)
axisY.setShadesBrush(QBrush(QColor('#ffffff')))
# axisX.setShadesBrush(QBrush(QColor('#ffffff')))
axisY.setShadesVisible(True)
chart.addAxis(axisX, Qt.AlignBottom)
series.attachAxis(axisX)
axisX.setLabelsAngle(-90)
chart.addAxis(axisY, Qt.AlignLeft)
series.attachAxis(axisY)
chartView = QChartView(chart)
chartView.setRenderHint(QPainter.Antialiasing)
chart.axisY(series).setRange(min(y)-5, max(y)+5)
chart.legend().setVisible(False)
lay.addWidget(chartView) # !!! +++
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec())
Автор решения: Garp
→ Ссылка
from PySide6.QtWidgets import *
from PySide6.QtGui import *
from PySide6.QtCore import *
from PySide6.QtCharts import *
import pandas as pd
import sys
datafile = "example_csv_file.csv"
def read_csv_file( file, n):
df = pd.read_csv(file)
col = df.iloc[:, n]
return col.values.tolist()
# класс скрола
class ScrollChartClass(QWidget):
def __init__(self, chart):
super().__init__()
self.chart = chart
self.init_UI()
self.len_of_file = 0
def init_UI(self):
self.scroll = QScrollArea()
self.hbox = QHBoxLayout()
self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.scroll.setWidgetResizable(False)
self.scroll.setWidget(self.chart)
self.hbox.addWidget(self.scroll)
self.setLayout(self.hbox)
return
# класс графика
class ChartClass(QWidget):
def __init__(self, file, n):
super().__init__()
self.resize(10000, 200)
self.file = file
self.n = n
self.init_UI()
self.current_position = 0
def init_UI(self):
layout = QVBoxLayout()
view = self.create_linechart(self.file, self.n)
layout.addWidget(view)
self.setLayout(layout)
def create_linechart(self, file, n):
seriesData1, seriesData2 = QLineSeries(), QLineSeries()
data1 = read_csv_file(file, 1)
data2 = read_csv_file(file, 1)
seriesData1.setColor(QColor("green"))
seriesData2.setColor(QColor("red"))
for x in range(len(data1)):
seriesData1.append(QPointF(x, data1[x]))
seriesData2.append(QPointF(x, data2[x]))
chart = QChart()
chart.legend().setVisible(False)
chart.addSeries(seriesData1)
chart.addSeries(seriesData2)
chart.createDefaultAxes()
view = QChartView(chart)
view.setRenderHint(QPainter.Antialiasing)
chartview = QChartView(chart)
return chartview
if __name__ == '__main__':
app = QApplication(sys.argv)
chart = ChartClass(datafile, 1)
scroll = ScrollChartClass(chart)
scroll.show()
sys.exit(app.exec())



