aboutsummaryrefslogtreecommitdiffstats
path: root/examples/charts
diff options
context:
space:
mode:
Diffstat (limited to 'examples/charts')
-rw-r--r--examples/charts/areachart/areachart.py67
-rw-r--r--examples/charts/areachart/areachart.pyproject3
-rw-r--r--examples/charts/areachart/doc/areachart.pngbin0 -> 15491 bytes
-rw-r--r--examples/charts/areachart/doc/areachart.rst8
-rw-r--r--examples/charts/audio.py127
-rw-r--r--examples/charts/audio/audio.py90
-rw-r--r--examples/charts/audio/audio.pyproject3
-rw-r--r--examples/charts/audio/doc/audio.pngbin0 -> 24659 bytes
-rw-r--r--examples/charts/audio/doc/audio.rst8
-rw-r--r--examples/charts/barchart/barchart.py69
-rw-r--r--examples/charts/barchart/barchart.pyproject3
-rw-r--r--examples/charts/barchart/doc/barchart.pngbin0 -> 15717 bytes
-rw-r--r--examples/charts/barchart/doc/barchart.rst8
-rw-r--r--examples/charts/callout.py257
-rw-r--r--examples/charts/callout/callout.py220
-rw-r--r--examples/charts/callout/callout.pyproject3
-rw-r--r--examples/charts/callout/doc/callout.pngbin0 -> 30597 bytes
-rw-r--r--examples/charts/callout/doc/callout.rst8
-rw-r--r--examples/charts/chartthemes/README.md2
-rw-r--r--examples/charts/chartthemes/chartthemes.pyproject3
-rw-r--r--examples/charts/chartthemes/doc/chartthemes.pngbin0 -> 47895 bytes
-rw-r--r--examples/charts/chartthemes/doc/chartthemes.rst11
-rw-r--r--examples/charts/chartthemes/main.py247
-rw-r--r--examples/charts/chartthemes/themewidget.ui10
-rw-r--r--examples/charts/chartthemes/ui_themewidget.py51
-rw-r--r--examples/charts/donutbreakdown/doc/donutbreakdown.pngbin0 -> 50391 bytes
-rw-r--r--examples/charts/donutbreakdown/doc/donutbreakdown.rst8
-rw-r--r--examples/charts/donutbreakdown/donutbreakdown.py (renamed from examples/charts/donutbreakdown.py)101
-rw-r--r--examples/charts/donutbreakdown/donutbreakdown.pyproject3
-rw-r--r--examples/charts/dynamicspline/chart.py52
-rw-r--r--examples/charts/dynamicspline/doc/dynamicspline.rst15
-rw-r--r--examples/charts/dynamicspline/doc/dynamicspline1.pngbin0 -> 34292 bytes
-rw-r--r--examples/charts/dynamicspline/doc/dynamicspline2.pngbin0 -> 40347 bytes
-rw-r--r--examples/charts/dynamicspline/dynamicspline.pyproject3
-rw-r--r--examples/charts/dynamicspline/main.py27
-rw-r--r--examples/charts/legend/doc/legend.pngbin0 -> 22719 bytes
-rw-r--r--examples/charts/legend/doc/legend.rst20
-rw-r--r--examples/charts/legend/legend.py (renamed from examples/charts/legend.py)92
-rw-r--r--examples/charts/legend/legend.pyproject3
-rw-r--r--examples/charts/lineandbar.py116
-rw-r--r--examples/charts/lineandbar/doc/lineandbar.pngbin0 -> 14482 bytes
-rw-r--r--examples/charts/lineandbar/doc/lineandbar.rst11
-rw-r--r--examples/charts/lineandbar/lineandbar.py81
-rw-r--r--examples/charts/lineandbar/lineandbar.pyproject3
-rw-r--r--examples/charts/linechart/doc/linechart.pngbin0 -> 13485 bytes
-rw-r--r--examples/charts/linechart/doc/linechart.rst8
-rw-r--r--examples/charts/linechart/linechart.py47
-rw-r--r--examples/charts/linechart/linechart.pyproject3
-rw-r--r--examples/charts/logvalueaxis/doc/logvalueaxis.pngbin0 -> 25462 bytes
-rw-r--r--examples/charts/logvalueaxis/doc/logvalueaxis.rst8
-rw-r--r--examples/charts/logvalueaxis/logvalueaxis.py57
-rw-r--r--examples/charts/logvalueaxis/logvalueaxis.pyproject3
-rw-r--r--examples/charts/memoryusage.py125
-rw-r--r--examples/charts/memoryusage/doc/memoryusage.pngbin0 -> 6633 bytes
-rw-r--r--examples/charts/memoryusage/doc/memoryusage.rst9
-rw-r--r--examples/charts/memoryusage/memoryusage.py92
-rw-r--r--examples/charts/memoryusage/memoryusage.pyproject3
-rw-r--r--examples/charts/modeldata/doc/modeldata.pngbin0 -> 70926 bytes
-rw-r--r--examples/charts/modeldata/doc/modeldata.rst9
-rw-r--r--examples/charts/modeldata/modeldata.py (renamed from examples/charts/modeldata.py)93
-rw-r--r--examples/charts/modeldata/modeldata.pyproject3
-rw-r--r--examples/charts/nesteddonuts.py136
-rw-r--r--examples/charts/nesteddonuts/doc/nesteddonuts.pngbin0 -> 63338 bytes
-rw-r--r--examples/charts/nesteddonuts/doc/nesteddonuts.rst7
-rw-r--r--examples/charts/nesteddonuts/nesteddonuts.py100
-rw-r--r--examples/charts/nesteddonuts/nesteddonuts.pyproject3
-rw-r--r--examples/charts/percentbarchart.py98
-rw-r--r--examples/charts/percentbarchart/doc/percentbarchart.pngbin0 -> 10274 bytes
-rw-r--r--examples/charts/percentbarchart/doc/percentbarchart.rst17
-rw-r--r--examples/charts/percentbarchart/percentbarchart.py63
-rw-r--r--examples/charts/percentbarchart/percentbarchart.pyproject3
-rw-r--r--examples/charts/piechart/doc/piechart.pngbin0 -> 9644 bytes
-rw-r--r--examples/charts/piechart/doc/piechart.rst8
-rw-r--r--examples/charts/piechart/piechart.py50
-rw-r--r--examples/charts/piechart/piechart.pyproject3
-rw-r--r--examples/charts/pointconfiguration/chartwindow.py156
-rw-r--r--examples/charts/pointconfiguration/doc/pointconfiguration.pngbin0 -> 34991 bytes
-rw-r--r--examples/charts/pointconfiguration/doc/pointconfiguration.rst144
-rw-r--r--examples/charts/pointconfiguration/pointconfiguration.py17
-rw-r--r--examples/charts/pointconfiguration/pointconfiguration.pyproject3
-rw-r--r--examples/charts/pointselectionandmarkers/doc/pointselectionandmarkers.pngbin0 -> 47669 bytes
-rw-r--r--examples/charts/pointselectionandmarkers/doc/pointselectionandmarkers.rst72
-rw-r--r--examples/charts/pointselectionandmarkers/images/blue_triangle.pngbin0 -> 2220 bytes
-rw-r--r--examples/charts/pointselectionandmarkers/images/green_triangle.pngbin0 -> 1389 bytes
-rw-r--r--examples/charts/pointselectionandmarkers/markers.qrc6
-rw-r--r--examples/charts/pointselectionandmarkers/pointselectionandmarkers.py128
-rw-r--r--examples/charts/pointselectionandmarkers/pointselectionandmarkers.pyproject3
-rw-r--r--examples/charts/pointselectionandmarkers/rc_markers.py275
-rw-r--r--examples/charts/pointselectionandmarkers/utilities.py77
-rw-r--r--examples/charts/qmlpolarchart/View1.qml52
-rw-r--r--examples/charts/qmlpolarchart/View2.qml73
-rw-r--r--examples/charts/qmlpolarchart/View3.qml60
-rw-r--r--examples/charts/qmlpolarchart/doc/qmlpolarchart.pngbin0 -> 45305 bytes
-rw-r--r--examples/charts/qmlpolarchart/doc/qmlpolarchart.rst8
-rw-r--r--examples/charts/qmlpolarchart/main.qml63
-rw-r--r--examples/charts/qmlpolarchart/qmlpolarchart.py28
-rw-r--r--examples/charts/qmlpolarchart/qmlpolarchart.pyproject3
-rw-r--r--examples/charts/temperaturerecords/doc/temperaturerecords.pngbin0 -> 13035 bytes
-rw-r--r--examples/charts/temperaturerecords/doc/temperaturerecords.rst10
-rw-r--r--examples/charts/temperaturerecords/temperaturerecords.py60
-rw-r--r--examples/charts/temperaturerecords/temperaturerecords.pyproject3
101 files changed, 2689 insertions, 1233 deletions
diff --git a/examples/charts/areachart/areachart.py b/examples/charts/areachart/areachart.py
new file mode 100644
index 000000000..164264ff7
--- /dev/null
+++ b/examples/charts/areachart/areachart.py
@@ -0,0 +1,67 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the areachart example from Qt v6.x"""
+
+import sys
+from PySide6.QtCore import QPointF, Qt
+from PySide6.QtWidgets import QMainWindow, QApplication
+from PySide6.QtCharts import QChart, QChartView, QLineSeries, QAreaSeries
+from PySide6.QtGui import QGradient, QPen, QLinearGradient, QPainter
+
+
+class TestChart(QMainWindow):
+ def __init__(self):
+ super().__init__()
+
+ self.series_0 = QLineSeries()
+ self.series_1 = QLineSeries()
+
+ self.series_0.append(QPointF(1, 5))
+ self.series_0.append(QPointF(3, 7))
+ self.series_0.append(QPointF(7, 6))
+ self.series_0.append(QPointF(9, 7))
+ self.series_0.append(QPointF(12, 6))
+ self.series_0.append(QPointF(16, 7))
+ self.series_0.append(QPointF(18, 5))
+
+ self.series_1.append(QPointF(1, 3))
+ self.series_1.append(QPointF(3, 4))
+ self.series_1.append(QPointF(7, 3))
+ self.series_1.append(QPointF(8, 2))
+ self.series_1.append(QPointF(12, 3))
+ self.series_1.append(QPointF(16, 4))
+ self.series_1.append(QPointF(18, 3))
+
+ self.series = QAreaSeries(self.series_0, self.series_1)
+ self.series.setName("Batman")
+ self.pen = QPen(0x059605)
+ self.pen.setWidth(3)
+ self.series.setPen(self.pen)
+
+ self.gradient = QLinearGradient(QPointF(0, 0), QPointF(0, 1))
+ self.gradient.setColorAt(0.0, 0x3cc63c)
+ self.gradient.setColorAt(1.0, 0x26f626)
+ self.gradient.setCoordinateMode(QGradient.ObjectBoundingMode)
+ self.series.setBrush(self.gradient)
+
+ self.chart = QChart()
+ self.chart.addSeries(self.series)
+ self.chart.setTitle("Simple areachart example")
+ self.chart.createDefaultAxes()
+ self.chart.axes(Qt.Horizontal)[0].setRange(0, 20)
+ self.chart.axes(Qt.Vertical)[0].setRange(0, 10)
+
+ self._chart_view = QChartView(self.chart)
+ self._chart_view.setRenderHint(QPainter.Antialiasing)
+
+ self.setCentralWidget(self._chart_view)
+
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+
+ window = TestChart()
+ window.show()
+ window.resize(400, 300)
+ sys.exit(app.exec())
diff --git a/examples/charts/areachart/areachart.pyproject b/examples/charts/areachart/areachart.pyproject
new file mode 100644
index 000000000..b4a6f9d65
--- /dev/null
+++ b/examples/charts/areachart/areachart.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["areachart.py"]
+}
diff --git a/examples/charts/areachart/doc/areachart.png b/examples/charts/areachart/doc/areachart.png
new file mode 100644
index 000000000..d03838443
--- /dev/null
+++ b/examples/charts/areachart/doc/areachart.png
Binary files differ
diff --git a/examples/charts/areachart/doc/areachart.rst b/examples/charts/areachart/doc/areachart.rst
new file mode 100644
index 000000000..c6cd718d7
--- /dev/null
+++ b/examples/charts/areachart/doc/areachart.rst
@@ -0,0 +1,8 @@
+Area Chart Example
+==================
+
+The example shows how to create an area Chart
+
+.. image:: areachart.png
+ :width: 400
+ :alt: Area Chart Screenshot
diff --git a/examples/charts/audio.py b/examples/charts/audio.py
deleted file mode 100644
index 256fe3a96..000000000
--- a/examples/charts/audio.py
+++ /dev/null
@@ -1,127 +0,0 @@
-
-#############################################################################
-##
-## Copyright (C) 2018 The Qt Company Ltd.
-## Contact: http://www.qt.io/licensing/
-##
-## This file is part of the Qt for Python examples of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:BSD$
-## You may use this file under the terms of the BSD license as follows:
-##
-## "Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions are
-## met:
-## * Redistributions of source code must retain the above copyright
-## notice, this list of conditions and the following disclaimer.
-## * Redistributions in binary form must reproduce the above copyright
-## notice, this list of conditions and the following disclaimer in
-## the documentation and/or other materials provided with the
-## distribution.
-## * Neither the name of The Qt Company Ltd nor the names of its
-## contributors may be used to endorse or promote products derived
-## from this software without specific prior written permission.
-##
-##
-## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-"""PySide2 port of the charts/audio example from Qt v5.x"""
-
-import os
-import sys
-from PySide2.QtCharts import QtCharts
-from PySide2.QtCore import QPointF, QRect, QSize
-from PySide2.QtMultimedia import (QAudio, QAudioDeviceInfo, QAudioFormat,
- QAudioInput)
-from PySide2.QtWidgets import QApplication, QMainWindow, QMessageBox
-
-sampleCount = 2000
-resolution = 4
-
-class MainWindow(QMainWindow):
- def __init__(self, device):
- super(MainWindow, self).__init__()
-
- self.series = QtCharts.QLineSeries()
- self.chart = QtCharts.QChart()
- self.chart.addSeries(self.series)
- self.axisX = QtCharts.QValueAxis()
- self.axisX.setRange(0, sampleCount)
- self.axisX.setLabelFormat("%g")
- self.axisX.setTitleText("Samples")
- self.axisY = QtCharts.QValueAxis()
- self.axisY.setRange(-1, 1)
- self.axisY.setTitleText("Audio level")
- self.chart.setAxisX(self.axisX, self.series)
- self.chart.setAxisY(self.axisY, self.series)
- self.chart.legend().hide()
- self.chart.setTitle("Data from the microphone ({})".format(device.deviceName()))
-
- formatAudio = QAudioFormat()
- formatAudio.setSampleRate(8000)
- formatAudio.setChannelCount(1)
- formatAudio.setSampleSize(8)
- formatAudio.setCodec("audio/pcm")
- formatAudio.setByteOrder(QAudioFormat.LittleEndian)
- formatAudio.setSampleType(QAudioFormat.UnSignedInt)
-
- self.audioInput = QAudioInput(device, formatAudio, self)
- self.ioDevice = self.audioInput.start()
- self.ioDevice.readyRead.connect(self._readyRead)
-
- self.chartView = QtCharts.QChartView(self.chart)
- self.setCentralWidget(self.chartView)
-
- self.buffer = [QPointF(x, 0) for x in range(sampleCount)]
- self.series.append(self.buffer)
-
- def closeEvent(self, event):
- if self.audioInput is not None:
- self.audioInput.stop()
- event.accept()
-
- def _readyRead(self):
- data = self.ioDevice.readAll()
- availableSamples = data.size() // resolution
- start = 0
- if (availableSamples < sampleCount):
- start = sampleCount - availableSamples
- for s in range(start):
- self.buffer[s].setY(self.buffer[s + availableSamples].y())
-
- dataIndex = 0
- for s in range(start, sampleCount):
- value = (ord(data[dataIndex]) - 128) / 128
- self.buffer[s].setY(value)
- dataIndex = dataIndex + resolution
- self.series.replace(self.buffer)
-
-if __name__ == '__main__':
- app = QApplication(sys.argv)
-
- inputDevice = QAudioDeviceInfo.defaultInputDevice()
- if (inputDevice.isNull()):
- QMessageBox.warning(None, "audio", "There is no audio input device available.")
- sys.exit(-1)
-
- mainWin = MainWindow(inputDevice)
- mainWin.setWindowTitle("audio")
- availableGeometry = app.desktop().availableGeometry(mainWin)
- size = availableGeometry.height() * 3 / 4
- mainWin.resize(size, size)
- mainWin.show()
- sys.exit(app.exec_())
diff --git a/examples/charts/audio/audio.py b/examples/charts/audio/audio.py
new file mode 100644
index 000000000..8ba0b20c5
--- /dev/null
+++ b/examples/charts/audio/audio.py
@@ -0,0 +1,90 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the charts/audio example from Qt v5.x"""
+
+import sys
+from PySide6.QtCharts import QChart, QChartView, QLineSeries, QValueAxis
+from PySide6.QtCore import QPointF, Slot
+from PySide6.QtMultimedia import QAudioFormat, QAudioSource, QMediaDevices
+from PySide6.QtWidgets import QApplication, QMainWindow, QMessageBox
+
+
+SAMPLE_COUNT = 2000
+
+
+RESOLUTION = 4
+
+
+class MainWindow(QMainWindow):
+ def __init__(self, device):
+ super().__init__()
+
+ self._series = QLineSeries()
+ self._chart = QChart()
+ self._chart.addSeries(self._series)
+ self._axis_x = QValueAxis()
+ self._axis_x.setRange(0, SAMPLE_COUNT)
+ self._axis_x.setLabelFormat("%g")
+ self._axis_x.setTitleText("Samples")
+ self._axis_y = QValueAxis()
+ self._axis_y.setRange(-1, 1)
+ self._axis_y.setTitleText("Audio level")
+ self._chart.setAxisX(self._axis_x, self._series)
+ self._chart.setAxisY(self._axis_y, self._series)
+ self._chart.legend().hide()
+ name = device.description()
+ self._chart.setTitle(f"Data from the microphone ({name})")
+
+ format_audio = QAudioFormat()
+ format_audio.setSampleRate(8000)
+ format_audio.setChannelCount(1)
+ format_audio.setSampleFormat(QAudioFormat.UInt8)
+
+ self._audio_input = QAudioSource(device, format_audio, self)
+ self._io_device = self._audio_input.start()
+ self._io_device.readyRead.connect(self._readyRead)
+
+ self._chart_view = QChartView(self._chart)
+ self.setCentralWidget(self._chart_view)
+
+ self._buffer = [QPointF(x, 0) for x in range(SAMPLE_COUNT)]
+ self._series.append(self._buffer)
+
+ def closeEvent(self, event):
+ if self._audio_input is not None:
+ self._audio_input.stop()
+ event.accept()
+
+ @Slot()
+ def _readyRead(self):
+ data = self._io_device.readAll()
+ available_samples = data.size() // RESOLUTION
+ start = 0
+ if (available_samples < SAMPLE_COUNT):
+ start = SAMPLE_COUNT - available_samples
+ for s in range(start):
+ self._buffer[s].setY(self._buffer[s + available_samples].y())
+
+ data_index = 0
+ for s in range(start, SAMPLE_COUNT):
+ value = (ord(data[data_index]) - 128) / 128
+ self._buffer[s].setY(value)
+ data_index = data_index + RESOLUTION
+ self._series.replace(self._buffer)
+
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+
+ input_devices = QMediaDevices.audioInputs()
+ if not input_devices:
+ QMessageBox.warning(None, "audio", "There is no audio input device available.")
+ sys.exit(-1)
+ main_win = MainWindow(input_devices[0])
+ main_win.setWindowTitle("audio")
+ available_geometry = main_win.screen().availableGeometry()
+ size = available_geometry.height() * 3 / 4
+ main_win.resize(size, size)
+ main_win.show()
+ sys.exit(app.exec())
diff --git a/examples/charts/audio/audio.pyproject b/examples/charts/audio/audio.pyproject
new file mode 100644
index 000000000..00d15e1ab
--- /dev/null
+++ b/examples/charts/audio/audio.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["audio.py"]
+}
diff --git a/examples/charts/audio/doc/audio.png b/examples/charts/audio/doc/audio.png
new file mode 100644
index 000000000..15ee1f680
--- /dev/null
+++ b/examples/charts/audio/doc/audio.png
Binary files differ
diff --git a/examples/charts/audio/doc/audio.rst b/examples/charts/audio/doc/audio.rst
new file mode 100644
index 000000000..38394451d
--- /dev/null
+++ b/examples/charts/audio/doc/audio.rst
@@ -0,0 +1,8 @@
+Audio Example
+=============
+
+This example shows the drawing of dynamic data (microphone input).
+
+.. image:: audio.png
+ :width: 400
+ :alt: Audio Screenshot
diff --git a/examples/charts/barchart/barchart.py b/examples/charts/barchart/barchart.py
new file mode 100644
index 000000000..66126ad8a
--- /dev/null
+++ b/examples/charts/barchart/barchart.py
@@ -0,0 +1,69 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the linechart example from Qt v6.x"""
+
+import sys
+
+from PySide6.QtCharts import (QBarCategoryAxis, QBarSeries, QBarSet, QChart,
+ QChartView, QValueAxis)
+from PySide6.QtCore import Qt
+from PySide6.QtGui import QPainter
+from PySide6.QtWidgets import QApplication, QMainWindow
+
+
+class TestChart(QMainWindow):
+ def __init__(self):
+ super().__init__()
+
+ self.set_0 = QBarSet("Jane")
+ self.set_1 = QBarSet("John")
+ self.set_2 = QBarSet("Axel")
+ self.set_3 = QBarSet("Mary")
+ self.set_4 = QBarSet("Samantha")
+
+ self.set_0.append([1, 2, 3, 4, 5, 6])
+ self.set_1.append([5, 0, 0, 4, 0, 7])
+ self.set_2.append([3, 5, 8, 13, 8, 5])
+ self.set_3.append([5, 6, 7, 3, 4, 5])
+ self.set_4.append([9, 7, 5, 3, 1, 2])
+
+ self.series = QBarSeries()
+ self.series.append(self.set_0)
+ self.series.append(self.set_1)
+ self.series.append(self.set_2)
+ self.series.append(self.set_3)
+ self.series.append(self.set_4)
+
+ self.chart = QChart()
+ self.chart.addSeries(self.series)
+ self.chart.setTitle("Simple barchart example")
+ self.chart.setAnimationOptions(QChart.SeriesAnimations)
+
+ self.categories = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
+ self.axis_x = QBarCategoryAxis()
+ self.axis_x.append(self.categories)
+ self.chart.addAxis(self.axis_x, Qt.AlignBottom)
+ self.series.attachAxis(self.axis_x)
+
+ self.axis_y = QValueAxis()
+ self.axis_y.setRange(0, 15)
+ self.chart.addAxis(self.axis_y, Qt.AlignLeft)
+ self.series.attachAxis(self.axis_y)
+
+ self.chart.legend().setVisible(True)
+ self.chart.legend().setAlignment(Qt.AlignBottom)
+
+ self._chart_view = QChartView(self.chart)
+ self._chart_view.setRenderHint(QPainter.Antialiasing)
+
+ self.setCentralWidget(self._chart_view)
+
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+
+ window = TestChart()
+ window.show()
+ window.resize(420, 300)
+ sys.exit(app.exec())
diff --git a/examples/charts/barchart/barchart.pyproject b/examples/charts/barchart/barchart.pyproject
new file mode 100644
index 000000000..4ca819426
--- /dev/null
+++ b/examples/charts/barchart/barchart.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["barchart.py"]
+}
diff --git a/examples/charts/barchart/doc/barchart.png b/examples/charts/barchart/doc/barchart.png
new file mode 100644
index 000000000..da08217fc
--- /dev/null
+++ b/examples/charts/barchart/doc/barchart.png
Binary files differ
diff --git a/examples/charts/barchart/doc/barchart.rst b/examples/charts/barchart/doc/barchart.rst
new file mode 100644
index 000000000..b9a499721
--- /dev/null
+++ b/examples/charts/barchart/doc/barchart.rst
@@ -0,0 +1,8 @@
+Bar Chart Example
+==================
+
+The example shows how to create a Bar chart.
+
+.. image:: barchart.png
+ :width: 400
+ :alt: Bar Chart Screenshot
diff --git a/examples/charts/callout.py b/examples/charts/callout.py
deleted file mode 100644
index a7aff6282..000000000
--- a/examples/charts/callout.py
+++ /dev/null
@@ -1,257 +0,0 @@
-
-#############################################################################
-##
-## Copyright (C) 2018 The Qt Company Ltd.
-## Contact: http://www.qt.io/licensing/
-##
-## This file is part of the Qt for Python examples of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:BSD$
-## You may use this file under the terms of the BSD license as follows:
-##
-## "Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions are
-## met:
-## * Redistributions of source code must retain the above copyright
-## notice, this list of conditions and the following disclaimer.
-## * Redistributions in binary form must reproduce the above copyright
-## notice, this list of conditions and the following disclaimer in
-## the documentation and/or other materials provided with the
-## distribution.
-## * Neither the name of The Qt Company Ltd nor the names of its
-## contributors may be used to endorse or promote products derived
-## from this software without specific prior written permission.
-##
-##
-## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-"""PySide2 port of the Callout example from Qt v5.x"""
-
-import sys
-from PySide2.QtWidgets import (QApplication, QWidget, QGraphicsScene,
- QGraphicsView, QGraphicsSimpleTextItem, QGraphicsItem)
-from PySide2.QtCore import Qt, QPointF, QRectF, QRect
-from PySide2.QtCharts import QtCharts
-from PySide2.QtGui import QPainter, QFont, QFontMetrics, QPainterPath, QColor
-
-
-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()
-
- def boundingRect(self):
- anchor = self.mapFromParent(self._chart.mapToPosition(self._anchor))
- 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))
- if not self._rect.contains(anchor) and not self._anchor.isNull():
- point1 = QPointF()
- point2 = QPointF()
-
- # establish the position of the anchor point in relation to _rect
- above = anchor.y() <= self._rect.top()
- aboveCenter = (anchor.y() > self._rect.top() and
- anchor.y() <= self._rect.center().y())
- belowCenter = (anchor.y() > self._rect.center().y() and
- anchor.y() <= self._rect.bottom())
- below = anchor.y() > self._rect.bottom()
-
- onLeft = anchor.x() <= self._rect.left()
- leftOfCenter = (anchor.x() > self._rect.left() and
- anchor.x() <= self._rect.center().x())
- rightOfCenter = (anchor.x() > self._rect.center().x() and
- anchor.x() <= self._rect.right())
- onRight = anchor.x() > self._rect.right()
-
- # get the nearest _rect corner.
- x = (onRight + rightOfCenter) * self._rect.width()
- y = (below + belowCenter) * self._rect.height()
- cornerCase = ((above and onLeft) or (above and onRight) or
- (below and onLeft) or (below and onRight))
- vertical = abs(anchor.x() - x) > abs(anchor.y() - y)
-
- x1 = (x + leftOfCenter * 10 - rightOfCenter * 20 + cornerCase *
- int(not vertical) * (onLeft * 10 - onRight * 20))
- y1 = (y + aboveCenter * 10 - belowCenter * 20 + cornerCase *
- vertical * (above * 10 - below * 20))
- point1.setX(x1)
- point1.setY(y1)
-
- x2 = (x + leftOfCenter * 20 - rightOfCenter * 10 + cornerCase *
- int(not vertical) * (onLeft * 20 - onRight * 10))
- y2 = (y + aboveCenter * 20 - belowCenter * 10 + cornerCase *
- 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 mousePressEvent(self, event):
- event.setAccepted(True)
-
- def mouseMoveEvent(self, event):
- if event.buttons() & Qt.LeftButton:
- self.setPos(mapToParent(
- event.pos() - event.buttonDownPos(Qt.LeftButton)))
- event.setAccepted(True)
- else:
- event.setAccepted(False)
-
- def setText(self, text):
- self._text = text
- metrics = QFontMetrics(self._font)
- self._textRect = QRectF(metrics.boundingRect(
- QRect(0.0, 0.0, 150.0, 150.0),Qt.AlignLeft, self._text))
- self._textRect.translate(5, 5)
- self.prepareGeometryChange()
- self._rect = self._textRect.adjusted(-5, -5, 5, 5)
-
- def setAnchor(self, point):
- self._anchor = QPointF(point)
-
- def updateGeometry(self):
- self.prepareGeometryChange()
- self.setPos(self._chart.mapToPosition(
- self._anchor) + QPointF(10, -50))
-
-
-class View(QGraphicsView):
- def __init__(self, parent = None):
- super(View, self).__init__(parent)
- self.setScene(QGraphicsScene(self))
-
- self.setDragMode(QGraphicsView.NoDrag)
- self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
- self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
-
- # Chart
- self._chart = QtCharts.QChart()
- self._chart.setMinimumSize(640, 480)
- self._chart.setTitle("Hover the line to show callout. Click the line "
- "to make it stay")
- self._chart.legend().hide()
- self.series = QtCharts.QLineSeries()
- self.series.append(1, 3)
- self.series.append(4, 5)
- self.series.append(5, 4.5)
- self.series.append(7, 1)
- self.series.append(11, 2)
- self._chart.addSeries(self.series)
-
- self.series2 = QtCharts.QSplineSeries()
- self.series2.append(1.6, 1.4)
- self.series2.append(2.4, 3.5)
- self.series2.append(3.7, 2.5)
- self.series2.append(7, 4)
- self.series2.append(10, 2)
- self._chart.addSeries(self.series2)
-
- self._chart.createDefaultAxes()
- self._chart.setAcceptHoverEvents(True)
-
- self.setRenderHint(QPainter.Antialiasing)
- self.scene().addItem(self._chart)
-
- self._coordX = QGraphicsSimpleTextItem(self._chart)
- self._coordX.setPos(
- self._chart.size().width()/2 - 50, self._chart.size().height())
- self._coordX.setText("X: ");
- self._coordY = QGraphicsSimpleTextItem(self._chart)
- self._coordY.setPos(
- self._chart.size().width()/2 + 50, self._chart.size().height())
- self._coordY.setText("Y: ")
-
- self._callouts = []
- self._tooltip = Callout(self._chart)
-
- self.series.clicked.connect(self.keepCallout)
- self.series.hovered.connect(self.tooltip)
-
- self.series2.clicked.connect(self.keepCallout)
- self.series2.hovered.connect(self.tooltip)
-
- self.setMouseTracking(True)
-
- def resizeEvent(self, event):
- if self.scene():
- self.scene().setSceneRect(QRectF(QPointF(0, 0), event.size()))
- self._chart.resize(event.size())
- self._coordX.setPos(
- self._chart.size().width()/2 - 50,
- self._chart.size().height() - 20)
- self._coordY.setPos(
- self._chart.size().width()/2 + 50,
- self._chart.size().height() - 20)
- for callout in self._callouts:
- callout.updateGeometry()
- QGraphicsView.resizeEvent(self, event)
-
-
- def mouseMoveEvent(self, event):
- self._coordX.setText("X: {0:.2f}"
- .format(self._chart.mapToValue(event.pos()).x()))
- self._coordY.setText("Y: {0:.2f}"
- .format(self._chart.mapToValue(event.pos()).y()))
- QGraphicsView.mouseMoveEvent(self, event)
-
- def keepCallout(self):
- self._callouts.append(self._tooltip);
- self._tooltip = Callout(self._chart)
-
- def tooltip(self, point, state):
- if self._tooltip == 0:
- self._tooltip = Callout(self._chart)
-
- if state:
- self._tooltip.setText("X: {0:.2f} \nY: {1:.2f} "
- .format(point.x(),point.y()))
- self._tooltip.setAnchor(point)
- self._tooltip.setZValue(11)
- self._tooltip.updateGeometry()
- self._tooltip.show()
- else:
- self._tooltip.hide()
-
-
-if __name__ == "__main__":
- app = QApplication(sys.argv)
- v = View()
- v.show()
- sys.exit(app.exec_())
diff --git a/examples/charts/callout/callout.py b/examples/charts/callout/callout.py
new file mode 100644
index 000000000..622938d16
--- /dev/null
+++ b/examples/charts/callout/callout.py
@@ -0,0 +1,220 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the Callout example from Qt v5.x"""
+
+import sys
+from PySide6.QtWidgets import (QApplication, QGraphicsScene, QGraphicsView,
+ QGraphicsSimpleTextItem, QGraphicsItem)
+from PySide6.QtCore import Qt, QPointF, QRectF, QRect
+from PySide6.QtCharts import QChart, QLineSeries, QSplineSeries
+from PySide6.QtGui import QPainter, QFont, QFontMetrics, QPainterPath, QColor
+
+
+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()
+
+ def boundingRect(self):
+ anchor = self.mapFromParent(self._chart.mapToPosition(self._anchor))
+ 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))
+ if not self._rect.contains(anchor) and not self._anchor.isNull():
+ point1 = QPointF()
+ point2 = QPointF()
+
+ # establish the position of the anchor point in relation to _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()
+
+ # get the nearest _rect corner.
+ 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 mousePressEvent(self, event):
+ event.setAccepted(True)
+
+ def mouseMoveEvent(self, event):
+ if event.buttons() & Qt.LeftButton:
+ self.setPos(self.mapToParent(
+ event.pos() - event.buttonDownPos(Qt.LeftButton)))
+ event.setAccepted(True)
+ else:
+ event.setAccepted(False)
+
+ def set_text(self, text):
+ self._text = text
+ metrics = QFontMetrics(self._font)
+ self._textRect = QRectF(metrics.boundingRect(
+ QRect(0.0, 0.0, 150.0, 150.0), Qt.AlignLeft, self._text))
+ self._textRect.translate(5, 5)
+ self.prepareGeometryChange()
+ self._rect = self._textRect.adjusted(-5, -5, 5, 5)
+
+ def set_anchor(self, point):
+ self._anchor = QPointF(point)
+
+ def update_geometry(self):
+ self.prepareGeometryChange()
+ self.setPos(self._chart.mapToPosition(
+ self._anchor) + QPointF(10, -50))
+
+
+class View(QGraphicsView):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.setScene(QGraphicsScene(self))
+
+ self.setDragMode(QGraphicsView.NoDrag)
+ self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
+ self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
+
+ # Chart
+ self._chart = QChart()
+ self._chart.setMinimumSize(640, 480)
+ self._chart.setTitle("Hover the line to show callout. Click the line "
+ "to make it stay")
+ self._chart.legend().hide()
+ self.series = QLineSeries()
+ self.series.append(1, 3)
+ self.series.append(4, 5)
+ self.series.append(5, 4.5)
+ self.series.append(7, 1)
+ self.series.append(11, 2)
+ self._chart.addSeries(self.series)
+
+ self.series2 = QSplineSeries()
+ self.series2.append(1.6, 1.4)
+ self.series2.append(2.4, 3.5)
+ self.series2.append(3.7, 2.5)
+ self.series2.append(7, 4)
+ self.series2.append(10, 2)
+ self._chart.addSeries(self.series2)
+
+ self._chart.createDefaultAxes()
+ self._chart.setAcceptHoverEvents(True)
+
+ self.setRenderHint(QPainter.Antialiasing)
+ self.scene().addItem(self._chart)
+
+ self._coordX = QGraphicsSimpleTextItem(self._chart)
+ self._coordX.setPos(
+ self._chart.size().width() / 2 - 50, self._chart.size().height())
+ self._coordX.setText("X: ")
+ self._coordY = QGraphicsSimpleTextItem(self._chart)
+ self._coordY.setPos(
+ self._chart.size().width() / 2 + 50, self._chart.size().height())
+ self._coordY.setText("Y: ")
+
+ self._callouts = []
+ self._tooltip = Callout(self._chart)
+
+ self.series.clicked.connect(self.keep_callout)
+ self.series.hovered.connect(self.tooltip)
+
+ self.series2.clicked.connect(self.keep_callout)
+ self.series2.hovered.connect(self.tooltip)
+
+ self.setMouseTracking(True)
+
+ def resizeEvent(self, event):
+ if self.scene():
+ self.scene().setSceneRect(QRectF(QPointF(0, 0), event.size()))
+ self._chart.resize(event.size())
+ self._coordX.setPos(
+ self._chart.size().width() / 2 - 50,
+ self._chart.size().height() - 20)
+ self._coordY.setPos(
+ self._chart.size().width() / 2 + 50,
+ self._chart.size().height() - 20)
+ for callout in self._callouts:
+ callout.updateGeometry()
+ QGraphicsView.resizeEvent(self, event)
+
+ def mouseMoveEvent(self, event):
+ pos = self._chart.mapToValue(event.position().toPoint())
+ x = pos.x()
+ y = pos.y()
+ self._coordX.setText(f"X: {x:.2f}")
+ self._coordY.setText(f"Y: {y:.2f}")
+ QGraphicsView.mouseMoveEvent(self, event)
+
+ def keep_callout(self):
+ self._callouts.append(self._tooltip)
+ self._tooltip = Callout(self._chart)
+
+ def tooltip(self, point, state):
+ if self._tooltip == 0:
+ self._tooltip = Callout(self._chart)
+
+ if state:
+ x = point.x()
+ y = point.y()
+ self._tooltip.set_text(f"X: {x:.2f} \nY: {y:.2f} ")
+ self._tooltip.set_anchor(point)
+ self._tooltip.setZValue(11)
+ self._tooltip.update_geometry()
+ self._tooltip.show()
+ else:
+ self._tooltip.hide()
+
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+ v = View()
+ v.show()
+ sys.exit(app.exec())
diff --git a/examples/charts/callout/callout.pyproject b/examples/charts/callout/callout.pyproject
new file mode 100644
index 000000000..1360c97b4
--- /dev/null
+++ b/examples/charts/callout/callout.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["callout.py"]
+}
diff --git a/examples/charts/callout/doc/callout.png b/examples/charts/callout/doc/callout.png
new file mode 100644
index 000000000..19e4c9d69
--- /dev/null
+++ b/examples/charts/callout/doc/callout.png
Binary files differ
diff --git a/examples/charts/callout/doc/callout.rst b/examples/charts/callout/doc/callout.rst
new file mode 100644
index 000000000..eeba1ca48
--- /dev/null
+++ b/examples/charts/callout/doc/callout.rst
@@ -0,0 +1,8 @@
+Callout Example
+===============
+
+This example shows how to draw an additional element (a callout) on top of the chart.
+
+.. image:: callout.png
+ :width: 400
+ :alt: Callout Screenshot
diff --git a/examples/charts/chartthemes/README.md b/examples/charts/chartthemes/README.md
index e11fa93c5..1b1ab51f7 100644
--- a/examples/charts/chartthemes/README.md
+++ b/examples/charts/chartthemes/README.md
@@ -3,7 +3,7 @@
To generated the file `ui_themewidget.py`, the following
command need to be executed:
-`pyside2-uic themewidget.ui > ui_themewidget.py`
+`pyside6-uic themewidget.ui -o ui_themewidget.py`
Also, if you modify the UI file, then you would need
to run the previous command again.
diff --git a/examples/charts/chartthemes/chartthemes.pyproject b/examples/charts/chartthemes/chartthemes.pyproject
new file mode 100644
index 000000000..4a0b38795
--- /dev/null
+++ b/examples/charts/chartthemes/chartthemes.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "README.md", "themewidget.ui"]
+}
diff --git a/examples/charts/chartthemes/doc/chartthemes.png b/examples/charts/chartthemes/doc/chartthemes.png
new file mode 100644
index 000000000..327caf552
--- /dev/null
+++ b/examples/charts/chartthemes/doc/chartthemes.png
Binary files differ
diff --git a/examples/charts/chartthemes/doc/chartthemes.rst b/examples/charts/chartthemes/doc/chartthemes.rst
new file mode 100644
index 000000000..104c67959
--- /dev/null
+++ b/examples/charts/chartthemes/doc/chartthemes.rst
@@ -0,0 +1,11 @@
+Chart Themes Example
+====================
+
+The example shows the look and feel of the different built-in themes.
+
+This example shows the look and feel of the different built-in themes for some
+of the supported chart types.
+
+.. image:: chartthemes.png
+ :width: 400
+ :alt: Chart Themes Screenshot
diff --git a/examples/charts/chartthemes/main.py b/examples/charts/chartthemes/main.py
index 1ba725b7d..5787710ca 100644
--- a/examples/charts/chartthemes/main.py
+++ b/examples/charts/chartthemes/main.py
@@ -1,56 +1,22 @@
-#############################################################################
-##
-## Copyright (C) 2018 The Qt Company Ltd.
-## Contact: http://www.qt.io/licensing/
-##
-## This file is part of the Qt for Python examples of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:BSD$
-## You may use this file under the terms of the BSD license as follows:
-##
-## "Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions are
-## met:
-## * Redistributions of source code must retain the above copyright
-## notice, this list of conditions and the following disclaimer.
-## * Redistributions in binary form must reproduce the above copyright
-## notice, this list of conditions and the following disclaimer in
-## the documentation and/or other materials provided with the
-## distribution.
-## * Neither the name of The Qt Company Ltd nor the names of its
-## contributors may be used to endorse or promote products derived
-## from this software without specific prior written permission.
-##
-##
-## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-"""PySide2 port of the Chart Themes example from Qt v5.x"""
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the Chart Themes example from Qt v5.x"""
import sys
-from PySide2.QtCore import qApp, QPointF, Qt
-from PySide2.QtGui import QColor, QPainter, QPalette
-from PySide2.QtWidgets import (QApplication, QMainWindow, QSizePolicy,
- QWidget)
-from PySide2.QtCharts import QtCharts
+from PySide6.QtCore import QPointF, Qt
+from PySide6.QtGui import QColor, QPainter, QPalette
+from PySide6.QtWidgets import (QApplication, QMainWindow, QSizePolicy,
+ QWidget)
+from PySide6.QtCharts import (QAreaSeries, QBarSet, QChart, QChartView,
+ QLineSeries, QPieSeries, QScatterSeries,
+ QSplineSeries, QStackedBarSeries)
from ui_themewidget import Ui_ThemeWidgetForm as ui
from random import random, uniform
+
class ThemeWidget(QWidget):
def __init__(self, parent):
QWidget.__init__(self, parent)
@@ -61,7 +27,7 @@ class ThemeWidget(QWidget):
self.value_max = 10
self.value_count = 7
self.data_table = self.generate_random_data(self.list_count,
- self.value_max, self.value_count)
+ self.value_max, self.value_count)
self.ui.setupUi(self)
self.populate_themebox()
@@ -69,34 +35,33 @@ class ThemeWidget(QWidget):
self.populate_legendbox()
# Area Chart
- chart_view = QtCharts.QChartView(self.create_areachart())
+ chart_view = QChartView(self.create_areachart())
self.ui.gridLayout.addWidget(chart_view, 1, 0)
self.charts.append(chart_view)
# Pie Chart
- chart_view = QtCharts.QChartView(self.createPieChart())
- chart_view.setSizePolicy(QSizePolicy.Ignored,
- QSizePolicy.Ignored)
+ chart_view = QChartView(self.create_pie_chart())
+ chart_view.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
self.ui.gridLayout.addWidget(chart_view, 1, 1)
self.charts.append(chart_view)
# Line Chart
- chart_view = QtCharts.QChartView(self.createLineChart())
+ chart_view = QChartView(self.create_line_chart())
self.ui.gridLayout.addWidget(chart_view, 1, 2)
self.charts.append(chart_view)
# Bar Chart
- chart_view = QtCharts.QChartView(self.createBarChart())
+ chart_view = QChartView(self.create_bar_chart())
self.ui.gridLayout.addWidget(chart_view, 2, 0)
self.charts.append(chart_view)
# Spline Chart
- chart_view = QtCharts.QChartView(self.createSplineChart())
+ chart_view = QChartView(self.create_spline_chart())
self.ui.gridLayout.addWidget(chart_view, 2, 1)
self.charts.append(chart_view)
# Scatter Chart
- chart_view = QtCharts.QChartView(self.create_scatterchart())
+ chart_view = QChartView(self.create_scatterchart())
self.ui.gridLayout.addWidget(chart_view, 2, 2)
self.charts.append(chart_view)
@@ -104,13 +69,12 @@ class ThemeWidget(QWidget):
self.ui.antialiasCheckBox.setChecked(True)
# Set the colors from the light theme as default ones
- pal = qApp.palette()
+ pal = qApp.palette() # noqa: F821
pal.setColor(QPalette.Window, QColor(0xf0f0f0))
pal.setColor(QPalette.WindowText, QColor(0x404044))
- qApp.setPalette(pal)
-
- self.updateUI()
+ qApp.setPalette(pal) # noqa: F821
+ self.update_ui()
def generate_random_data(self, list_count, value_max, value_count):
data_table = []
@@ -122,7 +86,7 @@ class ThemeWidget(QWidget):
y_value += uniform(0, constant)
x_value = (j + random()) * constant
value = QPointF(x_value, y_value)
- label = "Slice {}: {}".format(i, j)
+ label = f"Slice {i}: {j}"
data_list.append((value, label))
data_table.append(data_list)
@@ -131,22 +95,22 @@ class ThemeWidget(QWidget):
def populate_themebox(self):
theme = self.ui.themeComboBox
- theme.addItem("Light", QtCharts.QChart.ChartThemeLight)
- theme.addItem("Blue Cerulean", QtCharts.QChart.ChartThemeBlueCerulean)
- theme.addItem("Dark", QtCharts.QChart.ChartThemeDark)
- theme.addItem("Brown Sand", QtCharts.QChart.ChartThemeBrownSand)
- theme.addItem("Blue NCS", QtCharts.QChart.ChartThemeBlueNcs)
- theme.addItem("High Contrast", QtCharts.QChart.ChartThemeHighContrast)
- theme.addItem("Blue Icy", QtCharts.QChart.ChartThemeBlueIcy)
- theme.addItem("Qt", QtCharts.QChart.ChartThemeQt)
+ theme.addItem("Light", QChart.ChartThemeLight)
+ theme.addItem("Blue Cerulean", QChart.ChartThemeBlueCerulean)
+ theme.addItem("Dark", QChart.ChartThemeDark)
+ theme.addItem("Brown Sand", QChart.ChartThemeBrownSand)
+ theme.addItem("Blue NCS", QChart.ChartThemeBlueNcs)
+ theme.addItem("High Contrast", QChart.ChartThemeHighContrast)
+ theme.addItem("Blue Icy", QChart.ChartThemeBlueIcy)
+ theme.addItem("Qt", QChart.ChartThemeQt)
def populate_animationbox(self):
animated = self.ui.animatedComboBox
- animated.addItem("No Animations", QtCharts.QChart.NoAnimation)
- animated.addItem("GridAxis Animations", QtCharts.QChart.GridAxisAnimations)
- animated.addItem("Series Animations", QtCharts.QChart.SeriesAnimations)
- animated.addItem("All Animations", QtCharts.QChart.AllAnimations)
+ animated.addItem("No Animations", QChart.NoAnimation)
+ animated.addItem("GridAxis Animations", QChart.GridAxisAnimations)
+ animated.addItem("Series Animations", QChart.SeriesAnimations)
+ animated.addItem("All Animations", QChart.AllAnimations)
def populate_legendbox(self):
legend = self.ui.legendComboBox
@@ -158,42 +122,44 @@ class ThemeWidget(QWidget):
legend.addItem("Legend Right", Qt.AlignRight)
def create_areachart(self):
- chart = QtCharts.QChart()
+ chart = QChart()
chart.setTitle("Area Chart")
# The lower series initialized to zero values
lower_series = None
name = "Series "
for i in range(len(self.data_table)):
- upper_series = QtCharts.QLineSeries(chart)
+ upper_series = QLineSeries(chart)
for j in range(len(self.data_table[i])):
data = self.data_table[i][j]
if lower_series:
- points = lower_series.pointsVector()
+ points = lower_series.points()
y_value = points[i].y() + data[0].y()
upper_series.append(QPointF(j, y_value))
else:
upper_series.append(QPointF(j, data[0].y()))
- area = QtCharts.QAreaSeries(upper_series, lower_series)
- area.setName("{}{}".format(name, i))
+ area = QAreaSeries(upper_series, lower_series)
+ area.setName(f"{name}{i}")
chart.addSeries(area)
lower_series = upper_series
chart.createDefaultAxes()
- chart.axisX().setRange(0, self.value_count - 1)
- chart.axisY().setRange(0, self.value_max)
+ axis_x = chart.axes(Qt.Horizontal)[0]
+ axis_x.setRange(0, self.value_count - 1)
+ axis_y = chart.axes(Qt.Vertical)[0]
+ axis_y.setRange(0, self.value_max)
# Add space to label to add space between labels and axis
- chart.axisY().setLabelFormat("%.1f ")
+ axis_y.setLabelFormat("%.1f ")
return chart
- def createBarChart(self):
- chart = QtCharts.QChart()
+ def create_bar_chart(self):
+ chart = QChart()
chart.setTitle("Bar chart")
- series = QtCharts.QStackedBarSeries(chart)
+ series = QStackedBarSeries(chart)
for i in range(len(self.data_table)):
- barset = QtCharts.QBarSet("Bar set {}".format(i))
+ barset = QBarSet(f"Bar set {i}")
for data in self.data_table[i]:
barset.append(data[0].y())
series.append(barset)
@@ -201,37 +167,40 @@ class ThemeWidget(QWidget):
chart.addSeries(series)
chart.createDefaultAxes()
- chart.axisY().setRange(0, self.value_max * 2)
+ axis_y = chart.axes(Qt.Vertical)[0]
+ axis_y.setRange(0, self.value_max * 2)
# Add space to label to add space between labels and axis
- chart.axisY().setLabelFormat("%.1f ")
+ axis_y.setLabelFormat("%.1f ")
return chart
- def createLineChart(self):
- chart = QtCharts.QChart()
+ def create_line_chart(self):
+ chart = QChart()
chart.setTitle("Line chart")
name = "Series "
for i, lst in enumerate(self.data_table):
- series = QtCharts.QLineSeries(chart)
+ series = QLineSeries(chart)
for data in lst:
series.append(data[0])
- series.setName("{}{}".format(name, i))
+ series.setName(f"{name}{i}")
chart.addSeries(series)
chart.createDefaultAxes()
- chart.axisX().setRange(0, self.value_max)
- chart.axisY().setRange(0, self.value_count)
+ axis_x = chart.axes(Qt.Horizontal)[0]
+ axis_x.setRange(0, self.value_max)
+ axis_y = chart.axes(Qt.Vertical)[0]
+ axis_y.setRange(0, self.value_count)
# Add space to label to add space between labels and axis
- chart.axisY().setLabelFormat("%.1f ")
+ axis_y.setLabelFormat("%.1f ")
return chart
- def createPieChart(self):
- chart = QtCharts.QChart()
+ def create_pie_chart(self):
+ chart = QChart()
chart.setTitle("Pie chart")
- series = QtCharts.QPieSeries(chart)
+ series = QPieSeries(chart)
for data in self.data_table[0]:
slc = series.append(data[1], data[0].y())
if data == self.data_table[0][0]:
@@ -245,45 +214,49 @@ class ThemeWidget(QWidget):
return chart
- def createSplineChart(self):
- chart = QtCharts.QChart()
+ def create_spline_chart(self):
+ chart = QChart()
chart.setTitle("Spline chart")
name = "Series "
for i, lst in enumerate(self.data_table):
- series = QtCharts.QSplineSeries(chart)
+ series = QSplineSeries(chart)
for data in lst:
series.append(data[0])
- series.setName("{}{}".format(name, i))
+ series.setName(f"{name}{i}")
chart.addSeries(series)
chart.createDefaultAxes()
- chart.axisX().setRange(0, self.value_max)
- chart.axisY().setRange(0, self.value_count)
+ axis_x = chart.axes(Qt.Horizontal)[0]
+ axis_x.setRange(0, self.value_max)
+ axis_y = chart.axes(Qt.Vertical)[0]
+ axis_y.setRange(0, self.value_count)
# Add space to label to add space between labels and axis
- chart.axisY().setLabelFormat("%.1f ")
+ axis_y.setLabelFormat("%.1f ")
return chart
def create_scatterchart(self):
- chart = QtCharts.QChart()
+ chart = QChart()
chart.setTitle("Scatter chart")
name = "Series "
for i, lst in enumerate(self.data_table):
- series = QtCharts.QScatterSeries(chart)
+ series = QScatterSeries(chart)
for data in lst:
series.append(data[0])
- series.setName("{}{}".format(name, i))
+ series.setName(f"{name}{i}")
chart.addSeries(series)
chart.createDefaultAxes()
- chart.axisX().setRange(0, self.value_max)
- chart.axisY().setRange(0, self.value_count)
+ axis_x = chart.axes(Qt.Horizontal)[0]
+ axis_x.setRange(0, self.value_max)
+ axis_y = chart.axes(Qt.Vertical)[0]
+ axis_y.setRange(0, self.value_count)
# Add space to label to add space between labels and axis
- chart.axisY().setLabelFormat("%.1f ")
+ axis_y.setLabelFormat("%.1f ")
return chart
- def updateUI(self):
+ def update_ui(self):
def set_colors(window_color, text_color):
pal = self.window().palette()
pal.setColor(QPalette.Window, window_color)
@@ -297,46 +270,26 @@ class ThemeWidget(QWidget):
chart_theme = self.charts[0].chart().theme()
if chart_theme != theme:
for chart_view in self.charts:
- if theme == 0:
- theme_name = QtCharts.QChart.ChartThemeLight
- elif theme == 1:
- theme_name = QtCharts.QChart.ChartThemeBlueCerulean
- elif theme == 2:
- theme_name = QtCharts.QChart.ChartThemeDark
- elif theme == 3:
- theme_name = QtCharts.QChart.ChartThemeBrownSand
- elif theme == 4:
- theme_name = QtCharts.QChart.ChartThemeBlueNcs
- elif theme == 5:
- theme_name = QtCharts.QChart.ChartThemeHighContrast
- elif theme == 6:
- theme_name = QtCharts.QChart.ChartThemeBlueIcy
- elif theme == 7:
- theme_name = QtCharts.QChart.ChartThemeQt
- else:
- theme_name = QtCharts.QChart.ChartThemeLight
-
- chart_view.chart().setTheme(theme_name)
+ chart_view.chart().setTheme(theme)
# Set palette colors based on selected theme
- if theme == QtCharts.QChart.ChartThemeLight:
+ if theme == QChart.ChartThemeLight:
set_colors(QColor(0xf0f0f0), QColor(0x404044))
- elif theme == QtCharts.QChart.ChartThemeDark:
+ elif theme == QChart.ChartThemeDark:
set_colors(QColor(0x121218), QColor(0xd6d6d6))
- elif theme == QtCharts.QChart.ChartThemeBlueCerulean:
+ elif theme == QChart.ChartThemeBlueCerulean:
set_colors(QColor(0x40434a), QColor(0xd6d6d6))
- elif theme == QtCharts.QChart.ChartThemeBrownSand:
+ elif theme == QChart.ChartThemeBrownSand:
set_colors(QColor(0x9e8965), QColor(0x404044))
- elif theme == QtCharts.QChart.ChartThemeBlueNcs:
+ elif theme == QChart.ChartThemeBlueNcs:
set_colors(QColor(0x018bba), QColor(0x404044))
- elif theme == QtCharts.QChart.ChartThemeHighContrast:
+ elif theme == QChart.ChartThemeHighContrast:
set_colors(QColor(0xffab03), QColor(0x181818))
- elif theme == QtCharts.QChart.ChartThemeBlueIcy:
+ elif theme == QChart.ChartThemeBlueIcy:
set_colors(QColor(0xcee7f0), QColor(0x404044))
else:
set_colors(QColor(0xf0f0f0), QColor(0x404044))
-
# Update antialiasing
checked = self.ui.antialiasCheckBox.isChecked()
for chart in self.charts:
@@ -347,20 +300,10 @@ class ThemeWidget(QWidget):
options = self.ui.animatedComboBox.itemData(idx)
if len(self.charts):
- chart = self.charts[0].chart()
- animation_options = chart.animationOptions()
+ animation_options = self.charts[0].chart().animationOptions()
if animation_options != options:
for chart_view in self.charts:
- options_name = QtCharts.QChart.NoAnimation
- if options == 0:
- options_name = QtCharts.QChart.NoAnimation
- elif options == 1:
- options_name = QtCharts.QChart.GridAxisAnimations
- elif options == 2:
- options_name = QtCharts.QChart.SeriesAnimations
- elif options == 3:
- options_name = QtCharts.QChart.AllAnimations
- chart_view.chart().setAnimationOptions(options_name)
+ chart_view.chart().setAnimationOptions(options)
# Update legend alignment
idx = self.ui.legendComboBox.currentIndex()
@@ -389,8 +332,8 @@ if __name__ == "__main__":
window = QMainWindow()
widget = ThemeWidget(None)
window.setCentralWidget(widget)
- available_geometry = app.desktop().availableGeometry(window)
+ available_geometry = window.screen().availableGeometry()
size = available_geometry.height() * 0.75
window.setFixedSize(size, size * 0.8)
window.show()
- sys.exit(app.exec_())
+ sys.exit(app.exec())
diff --git a/examples/charts/chartthemes/themewidget.ui b/examples/charts/chartthemes/themewidget.ui
index 9ea2bb7c4..ad1e02f06 100644
--- a/examples/charts/chartthemes/themewidget.ui
+++ b/examples/charts/chartthemes/themewidget.ui
@@ -76,28 +76,28 @@
<sender>themeComboBox</sender>
<signal>currentIndexChanged(int)</signal>
<receiver>ThemeWidgetForm</receiver>
- <slot>updateUI()</slot>
+ <slot>update_ui()</slot>
</connection>
<connection>
<sender>antialiasCheckBox</sender>
<signal>toggled(bool)</signal>
<receiver>ThemeWidgetForm</receiver>
- <slot>updateUI()</slot>
+ <slot>update_ui()</slot>
</connection>
<connection>
<sender>legendComboBox</sender>
<signal>currentIndexChanged(int)</signal>
<receiver>ThemeWidgetForm</receiver>
- <slot>updateUI()</slot>
+ <slot>update_ui()</slot>
</connection>
<connection>
<sender>animatedComboBox</sender>
<signal>currentIndexChanged(int)</signal>
<receiver>ThemeWidgetForm</receiver>
- <slot>updateUI()</slot>
+ <slot>update_ui()</slot>
</connection>
</connections>
<slots>
- <slot>updateUI()</slot>
+ <slot>update_ui()</slot>
</slots>
</ui>
diff --git a/examples/charts/chartthemes/ui_themewidget.py b/examples/charts/chartthemes/ui_themewidget.py
index aa673eea9..711615b3e 100644
--- a/examples/charts/chartthemes/ui_themewidget.py
+++ b/examples/charts/chartthemes/ui_themewidget.py
@@ -3,74 +3,80 @@
################################################################################
## Form generated from reading UI file 'themewidget.ui'
##
-## Created by: Qt User Interface Compiler version 5.14.0
+## Created by: Qt User Interface Compiler version 6.7.0
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
-from PySide2.QtCore import (QCoreApplication, QMetaObject, QObject, QPoint,
- QRect, QSize, QUrl, Qt)
-from PySide2.QtGui import (QColor, QFont, QIcon, QPixmap)
-from PySide2.QtWidgets import *
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+ QMetaObject, QObject, QPoint, QRect,
+ QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
+ QFont, QFontDatabase, QGradient, QIcon,
+ QImage, QKeySequence, QLinearGradient, QPainter,
+ QPalette, QPixmap, QRadialGradient, QTransform)
+from PySide6.QtWidgets import (QApplication, QCheckBox, QComboBox, QGridLayout,
+ QHBoxLayout, QLabel, QSizePolicy, QSpacerItem,
+ QWidget)
class Ui_ThemeWidgetForm(object):
def setupUi(self, ThemeWidgetForm):
- if ThemeWidgetForm.objectName():
+ if not ThemeWidgetForm.objectName():
ThemeWidgetForm.setObjectName(u"ThemeWidgetForm")
ThemeWidgetForm.resize(900, 600)
- self.gridLayout = QGridLayout(ThemeWidgetForm);
+ self.gridLayout = QGridLayout(ThemeWidgetForm)
self.gridLayout.setObjectName(u"gridLayout")
- self.horizontalLayout = QHBoxLayout();
+ self.horizontalLayout = QHBoxLayout()
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.themeLabel = QLabel(ThemeWidgetForm)
self.themeLabel.setObjectName(u"themeLabel")
- self.horizontalLayout.addWidget(self.themeLabel);
+ self.horizontalLayout.addWidget(self.themeLabel)
self.themeComboBox = QComboBox(ThemeWidgetForm)
self.themeComboBox.setObjectName(u"themeComboBox")
- self.horizontalLayout.addWidget(self.themeComboBox);
+ self.horizontalLayout.addWidget(self.themeComboBox)
self.animatedLabel = QLabel(ThemeWidgetForm)
self.animatedLabel.setObjectName(u"animatedLabel")
- self.horizontalLayout.addWidget(self.animatedLabel);
+ self.horizontalLayout.addWidget(self.animatedLabel)
self.animatedComboBox = QComboBox(ThemeWidgetForm)
self.animatedComboBox.setObjectName(u"animatedComboBox")
- self.horizontalLayout.addWidget(self.animatedComboBox);
+ self.horizontalLayout.addWidget(self.animatedComboBox)
self.legendLabel = QLabel(ThemeWidgetForm)
self.legendLabel.setObjectName(u"legendLabel")
- self.horizontalLayout.addWidget(self.legendLabel);
+ self.horizontalLayout.addWidget(self.legendLabel)
self.legendComboBox = QComboBox(ThemeWidgetForm)
self.legendComboBox.setObjectName(u"legendComboBox")
- self.horizontalLayout.addWidget(self.legendComboBox);
+ self.horizontalLayout.addWidget(self.legendComboBox)
self.antialiasCheckBox = QCheckBox(ThemeWidgetForm)
self.antialiasCheckBox.setObjectName(u"antialiasCheckBox")
self.antialiasCheckBox.setChecked(False)
- self.horizontalLayout.addWidget(self.antialiasCheckBox);
+ self.horizontalLayout.addWidget(self.antialiasCheckBox)
- self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum);
+ self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
- self.horizontalLayout.addItem(self.horizontalSpacer);
+ self.horizontalLayout.addItem(self.horizontalSpacer)
- self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 3);
+ self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 3)
self.retranslateUi(ThemeWidgetForm)
- self.themeComboBox.currentIndexChanged.connect(ThemeWidgetForm.updateUI);
- self.antialiasCheckBox.toggled.connect(ThemeWidgetForm.updateUI);
- self.legendComboBox.currentIndexChanged.connect(ThemeWidgetForm.updateUI);
- self.animatedComboBox.currentIndexChanged.connect(ThemeWidgetForm.updateUI);
+ self.themeComboBox.currentIndexChanged.connect(ThemeWidgetForm.update_ui)
+ self.antialiasCheckBox.toggled.connect(ThemeWidgetForm.update_ui)
+ self.legendComboBox.currentIndexChanged.connect(ThemeWidgetForm.update_ui)
+ self.animatedComboBox.currentIndexChanged.connect(ThemeWidgetForm.update_ui)
QMetaObject.connectSlotsByName(ThemeWidgetForm)
# setupUi
@@ -80,5 +86,6 @@ class Ui_ThemeWidgetForm(object):
self.animatedLabel.setText(QCoreApplication.translate("ThemeWidgetForm", u"Animation:", None))
self.legendLabel.setText(QCoreApplication.translate("ThemeWidgetForm", u"Legend:", None))
self.antialiasCheckBox.setText(QCoreApplication.translate("ThemeWidgetForm", u"Anti-aliasing", None))
+ pass
# retranslateUi
diff --git a/examples/charts/donutbreakdown/doc/donutbreakdown.png b/examples/charts/donutbreakdown/doc/donutbreakdown.png
new file mode 100644
index 000000000..6499a8790
--- /dev/null
+++ b/examples/charts/donutbreakdown/doc/donutbreakdown.png
Binary files differ
diff --git a/examples/charts/donutbreakdown/doc/donutbreakdown.rst b/examples/charts/donutbreakdown/doc/donutbreakdown.rst
new file mode 100644
index 000000000..3e21d19e5
--- /dev/null
+++ b/examples/charts/donutbreakdown/doc/donutbreakdown.rst
@@ -0,0 +1,8 @@
+Donut Chart Breakdown Example
+=============================
+
+This example shows how to use create a donut breakdown chart using QPieSeries API.
+
+.. image:: donutbreakdown.png
+ :width: 400
+ :alt: Donut Chart Breakdown Screenshot
diff --git a/examples/charts/donutbreakdown.py b/examples/charts/donutbreakdown/donutbreakdown.py
index 28a48b8ac..9111d4aac 100644
--- a/examples/charts/donutbreakdown.py
+++ b/examples/charts/donutbreakdown/donutbreakdown.py
@@ -1,55 +1,19 @@
-#############################################################################
-##
-## Copyright (C) 2018 The Qt Company Ltd.
-## Contact: http://www.qt.io/licensing/
-##
-## This file is part of the Qt for Python examples of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:BSD$
-## You may use this file under the terms of the BSD license as follows:
-##
-## "Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions are
-## met:
-## * Redistributions of source code must retain the above copyright
-## notice, this list of conditions and the following disclaimer.
-## * Redistributions in binary form must reproduce the above copyright
-## notice, this list of conditions and the following disclaimer in
-## the documentation and/or other materials provided with the
-## distribution.
-## * Neither the name of The Qt Company Ltd nor the names of its
-## contributors may be used to endorse or promote products derived
-## from this software without specific prior written permission.
-##
-##
-## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-"""PySide2 port of the Donut Chart Breakdown example from Qt v5.x"""
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the Donut Chart Breakdown example from Qt v5.x"""
import sys
-from PySide2.QtCore import Qt
-from PySide2.QtGui import QColor, QFont, QPainter
-from PySide2.QtWidgets import QApplication, QMainWindow
-from PySide2.QtCharts import QtCharts
+from PySide6.QtCore import Qt, Slot
+from PySide6.QtGui import QColor, QFont, QPainter
+from PySide6.QtWidgets import QApplication, QMainWindow
+from PySide6.QtCharts import QChart, QChartView, QPieSeries, QPieSlice
+
-class MainSlice(QtCharts.QPieSlice):
+class MainSlice(QPieSlice):
def __init__(self, breakdown_series, parent=None):
- super(MainSlice, self).__init__(parent)
+ super().__init__(parent)
self.breakdown_series = breakdown_series
self.name = None
@@ -59,21 +23,23 @@ class MainSlice(QtCharts.QPieSlice):
def get_breakdown_series(self):
return self.breakdown_series
- def setName(self, name):
+ def set_name(self, name):
self.name = name
def name(self):
return self.name
+ @Slot()
def update_label(self):
- self.setLabel("{} {:.2f}%".format(self.name,
- self.percentage() * 100))
+ p = self.percentage() * 100
+ self.setLabel(f"{self.name} {p:.2f}%")
-class DonutBreakdownChart(QtCharts.QChart):
+class DonutBreakdownChart(QChart):
def __init__(self, parent=None):
- super(DonutBreakdownChart, self).__init__(QtCharts.QChart.ChartTypeCartesian, parent, Qt.WindowFlags())
- self.main_series = QtCharts.QPieSeries()
+ super().__init__(QChart.ChartTypeCartesian,
+ parent, Qt.WindowFlags())
+ self.main_series = QPieSeries()
self.main_series.setPieSize(0.7)
self.addSeries(self.main_series)
@@ -82,7 +48,7 @@ class DonutBreakdownChart(QtCharts.QChart):
# add breakdown series as a slice to center pie
main_slice = MainSlice(breakdown_series)
- main_slice.setName(breakdown_series.name())
+ main_slice.set_name(breakdown_series.name())
main_slice.setValue(breakdown_series.sum())
self.main_series.append(main_slice)
@@ -90,7 +56,7 @@ class DonutBreakdownChart(QtCharts.QChart):
main_slice.setBrush(color)
main_slice.setLabelVisible()
main_slice.setLabelColor(Qt.white)
- main_slice.setLabelPosition(QtCharts.QPieSlice.LabelInsideHorizontal)
+ main_slice.setLabelPosition(QPieSlice.LabelInsideHorizontal)
main_slice.setLabelFont(font)
# position and customize the breakdown series
@@ -114,11 +80,11 @@ class DonutBreakdownChart(QtCharts.QChart):
def recalculate_angles(self):
angle = 0
- slices = self.main_series.slices();
+ slices = self.main_series.slices()
for pie_slice in slices:
breakdown_series = pie_slice.get_breakdown_series()
breakdown_series.setPieStartAngle(angle)
- angle += pie_slice.percentage() * 360.0 # full pie is 360.0
+ angle += pie_slice.percentage() * 360.0 # full pie is 360.0
breakdown_series.setPieEndAngle(angle)
def update_legend_markers(self):
@@ -131,38 +97,39 @@ class DonutBreakdownChart(QtCharts.QChart):
marker.setVisible(False)
else:
# modify markers from breakdown series
- marker.setLabel("{} {:.2f}%".format(
- marker.slice().label(),
- marker.slice().percentage() * 100, 0))
+ label = marker.slice().label()
+ p = marker.slice().percentage() * 100
+ marker.setLabel(f"{label} {p:.2f}%")
marker.setFont(QFont("Arial", 8))
+
if __name__ == "__main__":
app = QApplication(sys.argv)
# Graph is based on data of:
# 'Total consumption of energy increased by 10 per cent in 2010'
# Statistics Finland, 13 December 2011
# http://www.stat.fi/til/ekul/2010/ekul_2010_2011-12-13_tie_001_en.html
- series1 = QtCharts.QPieSeries()
+ series1 = QPieSeries()
series1.setName("Fossil fuels")
series1.append("Oil", 353295)
series1.append("Coal", 188500)
series1.append("Natural gas", 148680)
series1.append("Peat", 94545)
- series2 = QtCharts.QPieSeries()
+ series2 = QPieSeries()
series2.setName("Renewables")
series2.append("Wood fuels", 319663)
series2.append("Hydro power", 45875)
series2.append("Wind power", 1060)
- series3 = QtCharts.QPieSeries()
+ series3 = QPieSeries()
series3.setName("Others")
series3.append("Nuclear energy", 238789)
series3.append("Import energy", 37802)
series3.append("Other", 32441)
donut_breakdown = DonutBreakdownChart()
- donut_breakdown.setAnimationOptions(QtCharts.QChart.AllAnimations)
+ donut_breakdown.setAnimationOptions(QChart.AllAnimations)
donut_breakdown.setTitle("Total consumption of energy in Finland 2010")
donut_breakdown.legend().setAlignment(Qt.AlignRight)
donut_breakdown.add_breakdown_series(series1, Qt.red)
@@ -170,12 +137,12 @@ if __name__ == "__main__":
donut_breakdown.add_breakdown_series(series3, Qt.darkBlue)
window = QMainWindow()
- chart_view = QtCharts.QChartView(donut_breakdown)
+ chart_view = QChartView(donut_breakdown)
chart_view.setRenderHint(QPainter.Antialiasing)
window.setCentralWidget(chart_view)
- available_geometry = app.desktop().availableGeometry(window)
+ available_geometry = window.screen().availableGeometry()
size = available_geometry.height() * 0.75
window.resize(size, size * 0.8)
window.show()
- sys.exit(app.exec_())
+ sys.exit(app.exec())
diff --git a/examples/charts/donutbreakdown/donutbreakdown.pyproject b/examples/charts/donutbreakdown/donutbreakdown.pyproject
new file mode 100644
index 000000000..6225792da
--- /dev/null
+++ b/examples/charts/donutbreakdown/donutbreakdown.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["donutbreakdown.py"]
+}
diff --git a/examples/charts/dynamicspline/chart.py b/examples/charts/dynamicspline/chart.py
new file mode 100644
index 000000000..59ddef13f
--- /dev/null
+++ b/examples/charts/dynamicspline/chart.py
@@ -0,0 +1,52 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import random
+
+from PySide6.QtCharts import QChart, QSplineSeries, QValueAxis
+from PySide6.QtCore import Qt, QTimer, Slot
+from PySide6.QtGui import QPen
+
+
+class Chart(QChart):
+ def __init__(self, parent=None):
+ super().__init__(QChart.ChartTypeCartesian, parent, Qt.WindowFlags())
+ self._timer = QTimer()
+ self._series = QSplineSeries(self)
+ self._titles = []
+ self._axisX = QValueAxis()
+ self._axisY = QValueAxis()
+ self._step = 0
+ self._x = 5
+ self._y = 1
+
+ self._timer.timeout.connect(self.handleTimeout)
+ self._timer.setInterval(1000)
+
+ green = QPen(Qt.red)
+ green.setWidth(3)
+ self._series.setPen(green)
+ self._series.append(self._x, self._y)
+
+ self.addSeries(self._series)
+ self.addAxis(self._axisX, Qt.AlignBottom)
+ self.addAxis(self._axisY, Qt.AlignLeft)
+
+ self._series.attachAxis(self._axisX)
+ self._series.attachAxis(self._axisY)
+ self._axisX.setTickCount(5)
+ self._axisX.setRange(0, 10)
+ self._axisY.setRange(-5, 10)
+
+ self._timer.start()
+
+ @Slot()
+ def handleTimeout(self):
+ x = self.plotArea().width() / self._axisX.tickCount()
+ y = (self._axisX.max() - self._axisX.min()) / self._axisX.tickCount()
+ self._x += y
+ self._y = random.uniform(0, 5) - 2.5
+ self._series.append(self._x, self._y)
+ self.scroll(x, 0)
+ if self._x == 100:
+ self._timer.stop()
diff --git a/examples/charts/dynamicspline/doc/dynamicspline.rst b/examples/charts/dynamicspline/doc/dynamicspline.rst
new file mode 100644
index 000000000..e946447b7
--- /dev/null
+++ b/examples/charts/dynamicspline/doc/dynamicspline.rst
@@ -0,0 +1,15 @@
+Dynamic Spline Example
+======================
+
+This example shows how to draw dynamic data.
+
+You can check a simple animation of this example
+`here <https://qt-wiki-uploads.s3.amazonaws.com/images/thumb/f/f8/Dynamicspline.gif/300px-Dynamicspline.gif>`_.
+
+.. image:: dynamicspline1.png
+ :width: 400
+ :alt: Dynamic Spline Screenshot 1
+
+.. image:: dynamicspline2.png
+ :width: 400
+ :alt: Dynamic Spline Screenshot 2
diff --git a/examples/charts/dynamicspline/doc/dynamicspline1.png b/examples/charts/dynamicspline/doc/dynamicspline1.png
new file mode 100644
index 000000000..bcee80ed4
--- /dev/null
+++ b/examples/charts/dynamicspline/doc/dynamicspline1.png
Binary files differ
diff --git a/examples/charts/dynamicspline/doc/dynamicspline2.png b/examples/charts/dynamicspline/doc/dynamicspline2.png
new file mode 100644
index 000000000..595c38b1f
--- /dev/null
+++ b/examples/charts/dynamicspline/doc/dynamicspline2.png
Binary files differ
diff --git a/examples/charts/dynamicspline/dynamicspline.pyproject b/examples/charts/dynamicspline/dynamicspline.pyproject
new file mode 100644
index 000000000..bdd641930
--- /dev/null
+++ b/examples/charts/dynamicspline/dynamicspline.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["chart.py", "main.py"]
+}
diff --git a/examples/charts/dynamicspline/main.py b/examples/charts/dynamicspline/main.py
new file mode 100644
index 000000000..8405824dc
--- /dev/null
+++ b/examples/charts/dynamicspline/main.py
@@ -0,0 +1,27 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the Dynamic Spline example from Qt v5.x"""
+import sys
+
+from PySide6.QtCharts import QChart, QChartView
+from PySide6.QtGui import QPainter
+from PySide6.QtWidgets import QApplication, QMainWindow
+
+from chart import Chart
+
+if __name__ == "__main__":
+
+ a = QApplication(sys.argv)
+ window = QMainWindow()
+ chart = Chart()
+ chart.setTitle("Dynamic spline chart")
+ chart.legend().hide()
+ chart.setAnimationOptions(QChart.AllAnimations)
+ chart_view = QChartView(chart)
+ chart_view.setRenderHint(QPainter.Antialiasing)
+ window.setCentralWidget(chart_view)
+ window.resize(400, 300)
+ window.show()
+
+ sys.exit(a.exec())
diff --git a/examples/charts/legend/doc/legend.png b/examples/charts/legend/doc/legend.png
new file mode 100644
index 000000000..1adc3d75b
--- /dev/null
+++ b/examples/charts/legend/doc/legend.png
Binary files differ
diff --git a/examples/charts/legend/doc/legend.rst b/examples/charts/legend/doc/legend.rst
new file mode 100644
index 000000000..10fb79cc1
--- /dev/null
+++ b/examples/charts/legend/doc/legend.rst
@@ -0,0 +1,20 @@
+Legend Example
+==============
+
+This example shows how to detach the legend from the chart and how to attach it
+back.
+
+By default the chart draws the legend inside the same view with the chart. In
+some cases the user may want to draw the legend to somewhere else. To make this
+possible the legend can be detached from the chart. Detaching means that the
+chart doesn't draw the legend or try to change its layout. The detached legend can
+then be drawn wherever the user wishes, for example, in a different graphics
+scene. The behavior of the legend can be inspected by running the legend
+example. In the example we use the bar series where we add or remove the bar
+sets. The legend reflects the changes in the series. The legend can be detached or
+attached back to the chart and its alignment can be modified. When the legend
+is detached, it can be resized and positioned freely.
+
+.. image:: legend.png
+ :width: 400
+ :alt: Legend Screenshot
diff --git a/examples/charts/legend.py b/examples/charts/legend/legend.py
index 47099e729..5417a940f 100644
--- a/examples/charts/legend.py
+++ b/examples/charts/legend/legend.py
@@ -1,57 +1,22 @@
-#############################################################################
-##
-## Copyright (C) 2018 The Qt Company Ltd.
-## Contact: http://www.qt.io/licensing/
-##
-## This file is part of the Qt for Python examples of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:BSD$
-## You may use this file under the terms of the BSD license as follows:
-##
-## "Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions are
-## met:
-## * Redistributions of source code must retain the above copyright
-## notice, this list of conditions and the following disclaimer.
-## * Redistributions in binary form must reproduce the above copyright
-## notice, this list of conditions and the following disclaimer in
-## the documentation and/or other materials provided with the
-## distribution.
-## * Neither the name of The Qt Company Ltd nor the names of its
-## contributors may be used to endorse or promote products derived
-## from this software without specific prior written permission.
-##
-##
-## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-"""PySide2 port of the Legend example from Qt v5.x"""
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the Legend example from Qt v5.x"""
import sys
-from PySide2.QtCore import Qt, QRectF
-from PySide2.QtGui import QBrush, QColor, QPainter, QPen
-from PySide2.QtWidgets import (QApplication, QDoubleSpinBox,
- QFormLayout, QGridLayout, QGroupBox, QPushButton, QWidget)
-from PySide2.QtCharts import QtCharts
+from PySide6.QtCore import Qt, QRectF, Slot
+from PySide6.QtGui import QBrush, QColor, QPainter, QPen
+from PySide6.QtWidgets import (QApplication, QDoubleSpinBox,
+ QFormLayout, QGridLayout, QGroupBox,
+ QPushButton, QWidget)
+from PySide6.QtCharts import QBarSeries, QBarSet, QChart, QChartView
+
class MainWidget(QWidget):
def __init__(self, parent=None):
- super(MainWidget, self).__init__(parent)
- self.chart = QtCharts.QChart()
- self.series = QtCharts.QBarSeries()
+ super().__init__(parent)
+ self.chart = QChart()
+ self.series = QBarSeries()
self.main_layout = QGridLayout()
self.button_layout = QGridLayout()
@@ -105,7 +70,7 @@ class MainWidget(QWidget):
self.legend_settings.setVisible(False)
# Create chart view with the chart
- self.chart_view = QtCharts.QChartView(self.chart, self)
+ self.chart_view = QChartView(self.chart, self)
# Create spinbox to modify font size
self.font_size.setValue(self.chart.legend().font().pointSizeF())
@@ -156,9 +121,10 @@ class MainWidget(QWidget):
self.legend_height.setMaximum(chart_viewrect.height())
self.legend_height.setValue(75)
- def hideLegendSpinbox(self):
+ def hide_legend_spinbox(self):
self.legend_settings.setVisible(False)
+ @Slot()
def toggle_attached(self):
legend = self.chart.legend()
if legend.isAttachedToChart():
@@ -172,22 +138,25 @@ class MainWidget(QWidget):
else:
legend.attachToChart()
legend.setBackgroundVisible(False)
- self.hideLegendSpinbox()
+ self.hide_legend_spinbox()
self.update()
+ @Slot()
def add_barset(self):
series_count = self.series.count()
- bar_set = QtCharts.QBarSet("set {}".format(series_count))
+ bar_set = QBarSet(f"set {series_count}")
delta = series_count * 0.1
bar_set.append([1 + delta, 2 + delta, 3 + delta, 4 + delta])
self.series.append(bar_set)
+ @Slot()
def remove_barset(self):
sets = self.series.barSets()
len_sets = len(sets)
if len_sets > 0:
self.series.remove(sets[len_sets - 1])
+ @Slot()
def set_legend_alignment(self):
button = self.sender()
legend = self.chart.legend()
@@ -210,43 +179,46 @@ class MainWidget(QWidget):
button.setText("Align (Top)")
legend.setAlignment(Qt.AlignTop)
+ @Slot()
def toggle_bold(self):
legend = self.chart.legend()
font = legend.font()
font.setBold(not font.bold())
legend.setFont(font)
+ @Slot()
def toggle_italic(self):
legend = self.chart.legend()
font = legend.font()
font.setItalic(not font.italic())
legend.setFont(font)
+ @Slot()
def font_size_changed(self):
legend = self.chart.legend()
font = legend.font()
- font_size = self.font_size.value()
+ font_size = self.font_size.value()
if font_size < 1:
font_size = 1
font.setPointSizeF(font_size)
legend.setFont(font)
+ @Slot()
def update_legend_layout(self):
legend = self.chart.legend()
- rect = QRectF(self.legend_posx.value(),
- self.legend_posy.value(),
- self.legend_width.value(),
- self.legend_height.value())
+ rect = QRectF(self.legend_posx.value(), self.legend_posy.value(),
+ self.legend_width.value(), self.legend_height.value())
legend.setGeometry(rect)
legend.update()
+
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MainWidget()
- available_geometry = app.desktop().availableGeometry(w)
+ available_geometry = w.screen().availableGeometry()
size = available_geometry.height() * 0.75
w.setFixedSize(size, size)
w.show()
- sys.exit(app.exec_())
+ sys.exit(app.exec())
diff --git a/examples/charts/legend/legend.pyproject b/examples/charts/legend/legend.pyproject
new file mode 100644
index 000000000..f130dcf01
--- /dev/null
+++ b/examples/charts/legend/legend.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["legend.py"]
+}
diff --git a/examples/charts/lineandbar.py b/examples/charts/lineandbar.py
deleted file mode 100644
index 0a29aa786..000000000
--- a/examples/charts/lineandbar.py
+++ /dev/null
@@ -1,116 +0,0 @@
-
-#############################################################################
-##
-## Copyright (C) 2018 The Qt Company Ltd.
-## Contact: http://www.qt.io/licensing/
-##
-## This file is part of the Qt for Python examples of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:BSD$
-## You may use this file under the terms of the BSD license as follows:
-##
-## "Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions are
-## met:
-## * Redistributions of source code must retain the above copyright
-## notice, this list of conditions and the following disclaimer.
-## * Redistributions in binary form must reproduce the above copyright
-## notice, this list of conditions and the following disclaimer in
-## the documentation and/or other materials provided with the
-## distribution.
-## * Neither the name of The Qt Company Ltd nor the names of its
-## contributors may be used to endorse or promote products derived
-## from this software without specific prior written permission.
-##
-##
-## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-"""PySide2 port of the line/bar example from Qt v5.x"""
-
-import sys
-from PySide2.QtCore import QPoint, Qt
-from PySide2.QtGui import QPainter
-from PySide2.QtWidgets import QMainWindow, QApplication
-from PySide2.QtCharts import QtCharts
-
-
-class TestChart(QMainWindow):
- def __init__(self):
- QMainWindow.__init__(self)
-
- self.set0 = QtCharts.QBarSet("Jane")
- self.set1 = QtCharts.QBarSet("John")
- self.set2 = QtCharts.QBarSet("Axel")
- self.set3 = QtCharts.QBarSet("Mary")
- self.set4 = QtCharts.QBarSet("Sam")
-
- self.set0.append([1, 2, 3, 4, 5, 6])
- self.set1.append([5, 0, 0, 4, 0, 7])
- self.set2.append([3, 5, 8, 13, 8, 5])
- self.set3.append([5, 6, 7, 3, 4, 5])
- self.set4.append([9, 7, 5, 3, 1, 2])
-
- self.barSeries = QtCharts.QBarSeries()
- self.barSeries.append(self.set0)
- self.barSeries.append(self.set1)
- self.barSeries.append(self.set2)
- self.barSeries.append(self.set3)
- self.barSeries.append(self.set4)
-
- self.lineSeries = QtCharts.QLineSeries()
- self.lineSeries.setName("trend")
- self.lineSeries.append(QPoint(0, 4))
- self.lineSeries.append(QPoint(1, 15))
- self.lineSeries.append(QPoint(2, 20))
- self.lineSeries.append(QPoint(3, 4))
- self.lineSeries.append(QPoint(4, 12))
- self.lineSeries.append(QPoint(5, 17))
-
- self.chart = QtCharts.QChart()
- self.chart.addSeries(self.barSeries)
- self.chart.addSeries(self.lineSeries)
- self.chart.setTitle("Line and barchart example")
-
- self.categories = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
- self.axisX = QtCharts.QBarCategoryAxis()
- self.axisX.append(self.categories)
- self.chart.setAxisX(self.axisX, self.lineSeries)
- self.chart.setAxisX(self.axisX, self.barSeries)
- self.axisX.setRange("Jan", "Jun")
-
- self.axisY = QtCharts.QValueAxis()
- self.chart.setAxisY(self.axisY, self.lineSeries)
- self.chart.setAxisY(self.axisY, self.barSeries)
- self.axisY.setRange(0, 20)
-
- self.chart.legend().setVisible(True)
- self.chart.legend().setAlignment(Qt.AlignBottom)
-
- self.chartView = QtCharts.QChartView(self.chart)
- self.chartView.setRenderHint(QPainter.Antialiasing)
-
- self.setCentralWidget(self.chartView)
-
-
-if __name__ == "__main__":
- app = QApplication(sys.argv)
-
- window = TestChart()
- window.show()
- window.resize(440, 300)
-
- sys.exit(app.exec_())
diff --git a/examples/charts/lineandbar/doc/lineandbar.png b/examples/charts/lineandbar/doc/lineandbar.png
new file mode 100644
index 000000000..a5c1fcea5
--- /dev/null
+++ b/examples/charts/lineandbar/doc/lineandbar.png
Binary files differ
diff --git a/examples/charts/lineandbar/doc/lineandbar.rst b/examples/charts/lineandbar/doc/lineandbar.rst
new file mode 100644
index 000000000..18dce9e59
--- /dev/null
+++ b/examples/charts/lineandbar/doc/lineandbar.rst
@@ -0,0 +1,11 @@
+Line and Bar Chart Example
+==========================
+
+The example shows how to combine different charts and set the axes.
+
+In the example, we combine a linechart with a barchart and use the category
+axis as a common axis for both.
+
+.. image:: lineandbar.png
+ :width: 400
+ :alt: Line and Bar Chart Screenshot
diff --git a/examples/charts/lineandbar/lineandbar.py b/examples/charts/lineandbar/lineandbar.py
new file mode 100644
index 000000000..62721c763
--- /dev/null
+++ b/examples/charts/lineandbar/lineandbar.py
@@ -0,0 +1,81 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the line/bar example from Qt v5.x"""
+
+import sys
+from PySide6.QtCore import QPoint, Qt
+from PySide6.QtGui import QPainter
+from PySide6.QtWidgets import QMainWindow, QApplication
+from PySide6.QtCharts import (QBarCategoryAxis, QBarSeries, QBarSet, QChart,
+ QChartView, QLineSeries, QValueAxis)
+
+
+class TestChart(QMainWindow):
+ def __init__(self):
+ super().__init__()
+
+ self.set0 = QBarSet("Jane")
+ self.set1 = QBarSet("John")
+ self.set2 = QBarSet("Axel")
+ self.set3 = QBarSet("Mary")
+ self.set4 = QBarSet("Sam")
+
+ self.set0.append([1, 2, 3, 4, 5, 6])
+ self.set1.append([5, 0, 0, 4, 0, 7])
+ self.set2.append([3, 5, 8, 13, 8, 5])
+ self.set3.append([5, 6, 7, 3, 4, 5])
+ self.set4.append([9, 7, 5, 3, 1, 2])
+
+ self._bar_series = QBarSeries()
+ self._bar_series.append(self.set0)
+ self._bar_series.append(self.set1)
+ self._bar_series.append(self.set2)
+ self._bar_series.append(self.set3)
+ self._bar_series.append(self.set4)
+
+ self._line_series = QLineSeries()
+ self._line_series.setName("trend")
+ self._line_series.append(QPoint(0, 4))
+ self._line_series.append(QPoint(1, 15))
+ self._line_series.append(QPoint(2, 20))
+ self._line_series.append(QPoint(3, 4))
+ self._line_series.append(QPoint(4, 12))
+ self._line_series.append(QPoint(5, 17))
+
+ self.chart = QChart()
+ self.chart.addSeries(self._bar_series)
+ self.chart.addSeries(self._line_series)
+ self.chart.setTitle("Line and barchart example")
+
+ self.categories = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
+ self._axis_x = QBarCategoryAxis()
+ self._axis_x.append(self.categories)
+ self.chart.addAxis(self._axis_x, Qt.AlignBottom)
+ self._line_series.attachAxis(self._axis_x)
+ self._bar_series.attachAxis(self._axis_x)
+ self._axis_x.setRange("Jan", "Jun")
+
+ self._axis_y = QValueAxis()
+ self.chart.addAxis(self._axis_x, Qt.AlignLeft)
+ self._line_series.attachAxis(self._axis_y)
+ self._bar_series.attachAxis(self._axis_y)
+ self._axis_y.setRange(0, 20)
+
+ self.chart.legend().setVisible(True)
+ self.chart.legend().setAlignment(Qt.AlignBottom)
+
+ self._chart_view = QChartView(self.chart)
+ self._chart_view.setRenderHint(QPainter.Antialiasing)
+
+ self.setCentralWidget(self._chart_view)
+
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+
+ window = TestChart()
+ window.show()
+ window.resize(440, 300)
+
+ sys.exit(app.exec())
diff --git a/examples/charts/lineandbar/lineandbar.pyproject b/examples/charts/lineandbar/lineandbar.pyproject
new file mode 100644
index 000000000..8d9010cf7
--- /dev/null
+++ b/examples/charts/lineandbar/lineandbar.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["lineandbar.py"]
+}
diff --git a/examples/charts/linechart/doc/linechart.png b/examples/charts/linechart/doc/linechart.png
new file mode 100644
index 000000000..9c32aabd5
--- /dev/null
+++ b/examples/charts/linechart/doc/linechart.png
Binary files differ
diff --git a/examples/charts/linechart/doc/linechart.rst b/examples/charts/linechart/doc/linechart.rst
new file mode 100644
index 000000000..b3daea3cf
--- /dev/null
+++ b/examples/charts/linechart/doc/linechart.rst
@@ -0,0 +1,8 @@
+Line Chart Example
+==================
+
+The example shows how to create a simple line chart.
+
+.. image:: linechart.png
+ :width: 400
+ :alt: Line Chart Screenshot
diff --git a/examples/charts/linechart/linechart.py b/examples/charts/linechart/linechart.py
new file mode 100644
index 000000000..cee4c16db
--- /dev/null
+++ b/examples/charts/linechart/linechart.py
@@ -0,0 +1,47 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the linechart example from Qt v5.x"""
+
+import sys
+from PySide6.QtCore import QPointF
+from PySide6.QtGui import QPainter
+from PySide6.QtWidgets import QMainWindow, QApplication
+from PySide6.QtCharts import QChart, QChartView, QLineSeries
+
+
+class TestChart(QMainWindow):
+ def __init__(self):
+ super().__init__()
+
+ self.series = QLineSeries()
+ self.series.append(0, 6)
+ self.series.append(2, 4)
+ self.series.append(3, 8)
+ self.series.append(7, 4)
+ self.series.append(10, 5)
+ self.series.append(QPointF(11, 1))
+ self.series.append(QPointF(13, 3))
+ self.series.append(QPointF(17, 6))
+ self.series.append(QPointF(18, 3))
+ self.series.append(QPointF(20, 2))
+
+ self.chart = QChart()
+ self.chart.legend().hide()
+ self.chart.addSeries(self.series)
+ self.chart.createDefaultAxes()
+ self.chart.setTitle("Simple line chart example")
+
+ self._chart_view = QChartView(self.chart)
+ self._chart_view.setRenderHint(QPainter.Antialiasing)
+
+ self.setCentralWidget(self._chart_view)
+
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+
+ window = TestChart()
+ window.show()
+ window.resize(440, 300)
+ sys.exit(app.exec())
diff --git a/examples/charts/linechart/linechart.pyproject b/examples/charts/linechart/linechart.pyproject
new file mode 100644
index 000000000..a0b84c285
--- /dev/null
+++ b/examples/charts/linechart/linechart.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["linechart.py"]
+}
diff --git a/examples/charts/logvalueaxis/doc/logvalueaxis.png b/examples/charts/logvalueaxis/doc/logvalueaxis.png
new file mode 100644
index 000000000..c25a5f4be
--- /dev/null
+++ b/examples/charts/logvalueaxis/doc/logvalueaxis.png
Binary files differ
diff --git a/examples/charts/logvalueaxis/doc/logvalueaxis.rst b/examples/charts/logvalueaxis/doc/logvalueaxis.rst
new file mode 100644
index 000000000..14c080a52
--- /dev/null
+++ b/examples/charts/logvalueaxis/doc/logvalueaxis.rst
@@ -0,0 +1,8 @@
+Logarithmic Axis Example
+========================
+
+The example shows how to use QLogValueAxis.
+
+.. image:: logvalueaxis.png
+ :width: 400
+ :alt: Logarithmic Axis Example Screenshot
diff --git a/examples/charts/logvalueaxis/logvalueaxis.py b/examples/charts/logvalueaxis/logvalueaxis.py
new file mode 100644
index 000000000..e727c1200
--- /dev/null
+++ b/examples/charts/logvalueaxis/logvalueaxis.py
@@ -0,0 +1,57 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the Logarithmic Axis Example from Qt v5.x"""
+
+
+import sys
+from PySide6.QtCore import Qt, QPointF
+from PySide6.QtGui import QPainter
+from PySide6.QtWidgets import QMainWindow, QApplication
+from PySide6.QtCharts import (QChart, QChartView, QLineSeries, QLogValueAxis,
+ QValueAxis)
+
+
+class TestChart(QMainWindow):
+ def __init__(self):
+ super().__init__()
+
+ self.series = QLineSeries()
+ self.series.append([
+ QPointF(1.0, 1.0), QPointF(2.0, 73.0), QPointF(3.0, 268.0),
+ QPointF(4.0, 17.0), QPointF(5.0, 4325.0), QPointF(6.0, 723.0)])
+
+ self.chart = QChart()
+ self.chart.addSeries(self.series)
+ self.chart.legend().hide()
+ self.chart.setTitle("Logarithmic axis example")
+
+ self._axis_x = QValueAxis()
+ self._axis_x.setTitleText("Data point")
+ self._axis_x.setLabelFormat("%i")
+ self._axis_x.setTickCount(self.series.count())
+ self.chart.addAxis(self._axis_x, Qt.AlignBottom)
+ self.series.attachAxis(self._axis_x)
+
+ self._axis_y = QLogValueAxis()
+ self._axis_y.setTitleText("Values")
+ self._axis_y.setLabelFormat("%g")
+ self._axis_y.setBase(8.0)
+ self._axis_y.setMinorTickCount(-1)
+ self.chart.addAxis(self._axis_y, Qt.AlignLeft)
+ self.series.attachAxis(self._axis_y)
+
+ self._chart_view = QChartView(self.chart)
+ self._chart_view.setRenderHint(QPainter.Antialiasing)
+
+ self.setCentralWidget(self._chart_view)
+
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+
+ window = TestChart()
+ window.show()
+ window.resize(800, 600)
+
+ sys.exit(app.exec())
diff --git a/examples/charts/logvalueaxis/logvalueaxis.pyproject b/examples/charts/logvalueaxis/logvalueaxis.pyproject
new file mode 100644
index 000000000..b6b3a8e74
--- /dev/null
+++ b/examples/charts/logvalueaxis/logvalueaxis.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["logvalueaxis.py"]
+}
diff --git a/examples/charts/memoryusage.py b/examples/charts/memoryusage.py
deleted file mode 100644
index b6f665b3d..000000000
--- a/examples/charts/memoryusage.py
+++ /dev/null
@@ -1,125 +0,0 @@
-
-#############################################################################
-##
-## Copyright (C) 2017 The Qt Company Ltd.
-## Contact: http://www.qt.io/licensing/
-##
-## This file is part of the Qt for Python examples of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:BSD$
-## You may use this file under the terms of the BSD license as follows:
-##
-## "Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions are
-## met:
-## * Redistributions of source code must retain the above copyright
-## notice, this list of conditions and the following disclaimer.
-## * Redistributions in binary form must reproduce the above copyright
-## notice, this list of conditions and the following disclaimer in
-## the documentation and/or other materials provided with the
-## distribution.
-## * Neither the name of The Qt Company Ltd nor the names of its
-## contributors may be used to endorse or promote products derived
-## from this software without specific prior written permission.
-##
-##
-## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-"""PySide2 Charts example: Simple memory usage viewer"""
-
-import os
-import sys
-from PySide2.QtCore import QRect, QSize, QProcess
-from PySide2.QtWidgets import QApplication, QMainWindow
-from PySide2.QtCharts import QtCharts
-
-def runProcess(command, arguments):
- process = QProcess()
- process.start(command, arguments)
- process.waitForFinished()
- std_output = process.readAllStandardOutput().data().decode('utf-8')
- return std_output.split('\n')
-
-def getMemoryUsage():
- result = []
- if sys.platform == 'win32':
- # Windows: Obtain memory usage in KB from 'tasklist'
- for line in runProcess('tasklist', [])[3:]:
- if len(line) >= 74:
- command = line[0:23].strip()
- if command.endswith('.exe'):
- command = command[0:len(command) - 4]
- memoryUsage = float(line[64:74].strip().replace(',', '').replace('.', ''))
- legend = ''
- if memoryUsage > 10240:
- legend = '{} {}M'.format(command, round(memoryUsage / 1024))
- else:
- legend = '{} {}K'.format(command, round(memoryUsage))
- result.append([legend, memoryUsage])
- else:
- # Unix: Obtain memory usage percentage from 'ps'
- psOptions = ['-e', 'v']
- memoryColumn = 8
- commandColumn = 9
- if sys.platform == 'darwin':
- psOptions = ['-e', '-v']
- memoryColumn = 11
- commandColumn = 12
- for line in runProcess('ps', psOptions):
- tokens = line.split(None)
- if len(tokens) > commandColumn and "PID" not in tokens: # Percentage and command
- command = tokens[commandColumn]
- if not command.startswith('['):
- command = os.path.basename(command)
- memoryUsage = round(float(tokens[memoryColumn].replace(',', '.')))
- legend = '{} {}%'.format(command, memoryUsage)
- result.append([legend, memoryUsage])
-
- result.sort(key = lambda x: x[1], reverse=True)
- return result
-
-class MainWindow(QMainWindow):
-
- def __init__(self):
- super(MainWindow, self).__init__()
-
- self.setWindowTitle('Memory Usage')
-
- memoryUsage = getMemoryUsage()
- if len(memoryUsage) > 5:
- memoryUsage = memoryUsage[0:4]
-
- self.series = QtCharts.QPieSeries()
- for item in memoryUsage:
- self.series.append(item[0], item[1]);
-
- slice = self.series.slices()[0]
- slice.setExploded();
- slice.setLabelVisible();
- self.chart = QtCharts.QChart()
- self.chart.addSeries(self.series);
- self.chartView = QtCharts.QChartView(self.chart)
- self.setCentralWidget(self.chartView)
-
-if __name__ == '__main__':
- app = QApplication(sys.argv)
- mainWin = MainWindow()
- availableGeometry = app.desktop().availableGeometry(mainWin)
- size = availableGeometry.height() * 3 / 4
- mainWin.resize(size, size)
- mainWin.show()
- sys.exit(app.exec_())
diff --git a/examples/charts/memoryusage/doc/memoryusage.png b/examples/charts/memoryusage/doc/memoryusage.png
new file mode 100644
index 000000000..de19d1602
--- /dev/null
+++ b/examples/charts/memoryusage/doc/memoryusage.png
Binary files differ
diff --git a/examples/charts/memoryusage/doc/memoryusage.rst b/examples/charts/memoryusage/doc/memoryusage.rst
new file mode 100644
index 000000000..59cac30d7
--- /dev/null
+++ b/examples/charts/memoryusage/doc/memoryusage.rst
@@ -0,0 +1,9 @@
+Memory Usag Example
+===================
+
+This example shows a QPieChart with the current memory usage in your
+computer.
+
+.. image:: memoryusage.png
+ :width: 400
+ :alt: Memory Usage Screenshot
diff --git a/examples/charts/memoryusage/memoryusage.py b/examples/charts/memoryusage/memoryusage.py
new file mode 100644
index 000000000..3ba42368e
--- /dev/null
+++ b/examples/charts/memoryusage/memoryusage.py
@@ -0,0 +1,92 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 Charts example: Simple memory usage viewer"""
+
+import os
+import sys
+from PySide6.QtCore import QProcess
+from PySide6.QtWidgets import QApplication, QMainWindow
+from PySide6.QtCharts import QChart, QChartView, QPieSeries
+
+
+def run_process(command, arguments):
+ process = QProcess()
+ process.start(command, arguments)
+ process.waitForFinished()
+ std_output = process.readAllStandardOutput().data().decode('utf-8')
+ return std_output.split('\n')
+
+
+def get_memory_usage():
+ result = []
+ if sys.platform == 'win32':
+ # Windows: Obtain memory usage in KB from 'tasklist'
+ for line in run_process('tasklist', [])[3:]:
+ if len(line) >= 74:
+ command = line[0:23].strip()
+ if command.endswith('.exe'):
+ command = command[0:len(command) - 4]
+ memory_usage = float(line[64:74].strip().replace(',', '').replace('.', ''))
+ legend = ''
+ if memory_usage > 10240:
+ mb = memory_usage / 1024
+ legend = f'{command} {mb}M'
+ else:
+ legend = f'{command} {memory_usage}K'
+ result.append([legend, memory_usage])
+ else:
+ # Unix: Obtain memory usage percentage from 'ps'
+ ps_options = ['-e', 'v']
+ memory_column = 8
+ command_column = 9
+ if sys.platform == 'darwin':
+ ps_options = ['-e', '-v']
+ memory_column = 11
+ command_column = 12
+ for line in run_process('ps', ps_options):
+ tokens = line.split(None)
+ if len(tokens) > command_column and "PID" not in tokens: # Percentage and command
+ command = tokens[command_column]
+ if not command.startswith('['):
+ command = os.path.basename(command)
+ memory_usage = round(float(tokens[memory_column].replace(',', '.')))
+ legend = f'{command} {memory_usage}%'
+ result.append([legend, memory_usage])
+
+ result.sort(key=lambda x: x[1], reverse=True)
+ return result
+
+
+class MainWindow(QMainWindow):
+
+ def __init__(self):
+ super().__init__()
+
+ self.setWindowTitle('Memory Usage')
+
+ memory_usage = get_memory_usage()
+ if len(memory_usage) > 5:
+ memory_usage = memory_usage[0:4]
+
+ self.series = QPieSeries()
+ for item in memory_usage:
+ self.series.append(item[0], item[1])
+
+ chart_slice = self.series.slices()[0]
+ chart_slice.setExploded()
+ chart_slice.setLabelVisible()
+ self.chart = QChart()
+ self.chart.addSeries(self.series)
+ self._chart_view = QChartView(self.chart)
+ self.setCentralWidget(self._chart_view)
+
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+ main_win = MainWindow()
+ available_geometry = main_win.screen().availableGeometry()
+ size = available_geometry.height() * 3 / 4
+ main_win.resize(size, size)
+ main_win.show()
+ sys.exit(app.exec())
diff --git a/examples/charts/memoryusage/memoryusage.pyproject b/examples/charts/memoryusage/memoryusage.pyproject
new file mode 100644
index 000000000..4a3c69ef6
--- /dev/null
+++ b/examples/charts/memoryusage/memoryusage.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["memoryusage.py"]
+}
diff --git a/examples/charts/modeldata/doc/modeldata.png b/examples/charts/modeldata/doc/modeldata.png
new file mode 100644
index 000000000..29cb57084
--- /dev/null
+++ b/examples/charts/modeldata/doc/modeldata.png
Binary files differ
diff --git a/examples/charts/modeldata/doc/modeldata.rst b/examples/charts/modeldata/doc/modeldata.rst
new file mode 100644
index 000000000..5d5d59e39
--- /dev/null
+++ b/examples/charts/modeldata/doc/modeldata.rst
@@ -0,0 +1,9 @@
+Model Data Example
+=====================
+
+This example shows how to use the QAbstractTableModel derived model as the data
+for the series.
+
+.. image:: modeldata.png
+ :width: 400
+ :alt: Model Data Screenshot
diff --git a/examples/charts/modeldata.py b/examples/charts/modeldata/modeldata.py
index be63cf3d2..0e36f7770 100644
--- a/examples/charts/modeldata.py
+++ b/examples/charts/modeldata/modeldata.py
@@ -1,65 +1,28 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-#############################################################################
-##
-## Copyright (C) 2018 The Qt Company Ltd.
-## Contact: http://www.qt.io/licensing/
-##
-## This file is part of the Qt for Python examples of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:BSD$
-## You may use this file under the terms of the BSD license as follows:
-##
-## "Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions are
-## met:
-## * Redistributions of source code must retain the above copyright
-## notice, this list of conditions and the following disclaimer.
-## * Redistributions in binary form must reproduce the above copyright
-## notice, this list of conditions and the following disclaimer in
-## the documentation and/or other materials provided with the
-## distribution.
-## * Neither the name of The Qt Company Ltd nor the names of its
-## contributors may be used to endorse or promote products derived
-## from this software without specific prior written permission.
-##
-##
-## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-"""PySide2 port of the Model Data example from Qt v5.x"""
+"""PySide6 port of the Model Data example from Qt v5.x"""
import sys
from random import randrange
-from PySide2.QtCore import QAbstractTableModel, QModelIndex, QRect, Qt
-from PySide2.QtGui import QColor, QPainter
-from PySide2.QtWidgets import (QApplication, QGridLayout, QHeaderView,
- QTableView, QWidget)
-from PySide2.QtCharts import QtCharts
+from PySide6.QtCore import QAbstractTableModel, QModelIndex, QRect, Qt
+from PySide6.QtGui import QColor, QPainter
+from PySide6.QtWidgets import (QApplication, QGridLayout, QHeaderView,
+ QTableView, QWidget)
+from PySide6.QtCharts import QChart, QChartView, QLineSeries, QVXYModelMapper
+
class CustomTableModel(QAbstractTableModel):
def __init__(self):
- QAbstractTableModel.__init__(self)
+ super().__init__()
self.input_data = []
self.mapping = {}
self.column_count = 4
self.row_count = 15
for i in range(self.row_count):
- data_vec = [0]*self.column_count
+ data_vec = [0] * self.column_count
for k in range(len(data_vec)):
if k % 2 == 0:
data_vec[k] = i * 50 + randrange(30)
@@ -83,7 +46,7 @@ class CustomTableModel(QAbstractTableModel):
else:
return "y"
else:
- return "{}".format(section + 1)
+ return str(section + 1)
def data(self, index, role=Qt.DisplayRole):
if role == Qt.DisplayRole:
@@ -95,7 +58,7 @@ class CustomTableModel(QAbstractTableModel):
if rect.contains(index.column(), index.row()):
return QColor(color)
# cell not mapped return white color
- return QColor(Qt.white);
+ return QColor(Qt.white)
return None
def setData(self, index, value, role=Qt.EditRole):
@@ -115,10 +78,9 @@ class CustomTableModel(QAbstractTableModel):
self.mapping = {}
-
class TableWidget(QWidget):
def __init__(self):
- QWidget.__init__(self)
+ super().__init__()
self.model = CustomTableModel()
@@ -127,30 +89,27 @@ class TableWidget(QWidget):
self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.table_view.verticalHeader().setSectionResizeMode(QHeaderView.Stretch)
- self.chart = QtCharts.QChart()
- self.chart.setAnimationOptions(QtCharts.QChart.AllAnimations)
+ self.chart = QChart()
+ self.chart.setAnimationOptions(QChart.AllAnimations)
- self.series = QtCharts.QLineSeries()
+ self.series = QLineSeries()
self.series.setName("Line 1")
- self.mapper = QtCharts.QVXYModelMapper(self)
+ self.mapper = QVXYModelMapper(self)
self.mapper.setXColumn(0)
self.mapper.setYColumn(1)
self.mapper.setSeries(self.series)
self.mapper.setModel(self.model)
self.chart.addSeries(self.series)
- # for storing color hex from the series
- seriesColorHex = "#000000"
-
# get the color of the series and use it for showing the mapped area
- seriesColorHex = "{}".format(self.series.pen().color().name())
- self.model.add_mapping(seriesColorHex, QRect(0, 0, 2, self.model.rowCount()))
+ self.model.add_mapping(self.series.pen().color().name(),
+ QRect(0, 0, 2, self.model.rowCount()))
# series 2
- self.series = QtCharts.QLineSeries()
+ self.series = QLineSeries()
self.series.setName("Line 2")
- self.mapper = QtCharts.QVXYModelMapper(self)
+ self.mapper = QVXYModelMapper(self)
self.mapper.setXColumn(2)
self.mapper.setYColumn(3)
self.mapper.setSeries(self.series)
@@ -158,11 +117,11 @@ class TableWidget(QWidget):
self.chart.addSeries(self.series)
# get the color of the series and use it for showing the mapped area
- seriesColorHex = "{}".format(self.series.pen().color().name())
- self.model.add_mapping(seriesColorHex, QRect(2, 0, 2, self.model.rowCount()));
+ self.model.add_mapping(self.series.pen().color().name(),
+ QRect(2, 0, 2, self.model.rowCount()))
self.chart.createDefaultAxes()
- self.chart_view = QtCharts.QChartView(self.chart)
+ self.chart_view = QChartView(self.chart)
self.chart_view.setRenderHint(QPainter.Antialiasing)
self.chart_view.setMinimumSize(640, 480)
@@ -179,4 +138,4 @@ if __name__ == "__main__":
app = QApplication(sys.argv)
w = TableWidget()
w.show()
- sys.exit(app.exec_())
+ sys.exit(app.exec())
diff --git a/examples/charts/modeldata/modeldata.pyproject b/examples/charts/modeldata/modeldata.pyproject
new file mode 100644
index 000000000..e10d49eb2
--- /dev/null
+++ b/examples/charts/modeldata/modeldata.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["modeldata.py"]
+}
diff --git a/examples/charts/nesteddonuts.py b/examples/charts/nesteddonuts.py
deleted file mode 100644
index 77bbabfc7..000000000
--- a/examples/charts/nesteddonuts.py
+++ /dev/null
@@ -1,136 +0,0 @@
-
-#############################################################################
-##
-## Copyright (C) 2018 The Qt Company Ltd.
-## Contact: http://www.qt.io/licensing/
-##
-## This file is part of the Qt for Python examples of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:BSD$
-## You may use this file under the terms of the BSD license as follows:
-##
-## "Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions are
-## met:
-## * Redistributions of source code must retain the above copyright
-## notice, this list of conditions and the following disclaimer.
-## * Redistributions in binary form must reproduce the above copyright
-## notice, this list of conditions and the following disclaimer in
-## the documentation and/or other materials provided with the
-## distribution.
-## * Neither the name of The Qt Company Ltd nor the names of its
-## contributors may be used to endorse or promote products derived
-## from this software without specific prior written permission.
-##
-##
-## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-"""PySide2 port of the Nested Donuts example from Qt v5.x"""
-
-import sys
-
-from PySide2.QtCore import Qt, QTimer
-from PySide2.QtGui import QPainter
-from PySide2.QtWidgets import QApplication, QGridLayout, QWidget
-from PySide2.QtCharts import QtCharts
-
-from random import randrange
-from functools import partial
-
-class Widget(QWidget):
- def __init__(self):
- QWidget.__init__(self)
- self.setMinimumSize(800, 600)
- self.donuts = []
- self.chart_view = QtCharts.QChartView()
- self.chart_view.setRenderHint(QPainter.Antialiasing)
- self.chart = self.chart_view.chart()
- self.chart.legend().setVisible(False)
- self.chart.setTitle("Nested donuts demo")
- self.chart.setAnimationOptions(QtCharts.QChart.AllAnimations)
-
- self.min_size = 0.1
- self.max_size = 0.9
- self.donut_count = 5
-
- self.setup_donuts()
-
- # create main layout
- self.main_layout = QGridLayout(self)
- self.main_layout.addWidget(self.chart_view, 1, 1)
- self.setLayout(self.main_layout)
-
- self.update_timer = QTimer(self)
- self.update_timer.timeout.connect(self.update_rotation)
- self.update_timer.start(1250)
-
- def setup_donuts(self):
- for i in range(self.donut_count):
- donut = QtCharts.QPieSeries()
- slccount = randrange(3, 6)
- for j in range(slccount):
- value = randrange(100, 200)
-
- slc = QtCharts.QPieSlice(str(value), value)
- slc.setLabelVisible(True)
- slc.setLabelColor(Qt.white)
- slc.setLabelPosition(QtCharts.QPieSlice.LabelInsideTangential)
-
- # Connection using an extra parameter for the slot
- slc.hovered[bool].connect(partial(self.explode_slice, slc=slc))
-
- donut.append(slc)
- size = (self.max_size - self.min_size)/self.donut_count
- donut.setHoleSize(self.min_size + i * size)
- donut.setPieSize(self.min_size + (i + 1) * size)
-
- self.donuts.append(donut)
- self.chart_view.chart().addSeries(donut)
-
-
-
- def update_rotation(self):
- for donut in self.donuts:
- phase_shift = randrange(-50, 100)
- donut.setPieStartAngle(donut.pieStartAngle() + phase_shift)
- donut.setPieEndAngle(donut.pieEndAngle() + phase_shift)
-
- def explode_slice(self, exploded, slc):
- if exploded:
- self.update_timer.stop()
- slice_startangle = slc.startAngle()
- slice_endangle = slc.startAngle() + slc.angleSpan()
-
- donut = slc.series()
- idx = self.donuts.index(donut)
- for i in range(idx + 1, len(self.donuts)):
- self.donuts[i].setPieStartAngle(slice_endangle)
- self.donuts[i].setPieEndAngle(360 + slice_startangle)
- else:
- for donut in self.donuts:
- donut.setPieStartAngle(0)
- donut.setPieEndAngle(360)
-
- self.update_timer.start()
-
- slc.setExploded(exploded)
-
-if __name__ == "__main__":
- app = QApplication(sys.argv)
- w = Widget()
- w.show()
- sys.exit(app.exec_())
diff --git a/examples/charts/nesteddonuts/doc/nesteddonuts.png b/examples/charts/nesteddonuts/doc/nesteddonuts.png
new file mode 100644
index 000000000..e1885081b
--- /dev/null
+++ b/examples/charts/nesteddonuts/doc/nesteddonuts.png
Binary files differ
diff --git a/examples/charts/nesteddonuts/doc/nesteddonuts.rst b/examples/charts/nesteddonuts/doc/nesteddonuts.rst
new file mode 100644
index 000000000..271ca61eb
--- /dev/null
+++ b/examples/charts/nesteddonuts/doc/nesteddonuts.rst
@@ -0,0 +1,7 @@
+Nested Donuts Example
+=====================
+
+This example shows how to create a nested donuts chart using the QPieSeries API.
+
+.. image:: nesteddonuts.png
+ :alt: Nested Donuts Screenshot
diff --git a/examples/charts/nesteddonuts/nesteddonuts.py b/examples/charts/nesteddonuts/nesteddonuts.py
new file mode 100644
index 000000000..49173c33a
--- /dev/null
+++ b/examples/charts/nesteddonuts/nesteddonuts.py
@@ -0,0 +1,100 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the Nested Donuts example from Qt v5.x"""
+
+import sys
+
+from PySide6.QtCore import Qt, QTimer, Slot
+from PySide6.QtGui import QPainter
+from PySide6.QtWidgets import QApplication, QGridLayout, QWidget
+from PySide6.QtCharts import QChart, QChartView, QPieSeries, QPieSlice
+
+
+from random import randrange
+from functools import partial
+
+
+class Widget(QWidget):
+ def __init__(self):
+ super().__init__()
+ self.setMinimumSize(800, 600)
+ self.donuts = []
+ self.chart_view = QChartView()
+ self.chart_view.setRenderHint(QPainter.Antialiasing)
+ self.chart = self.chart_view.chart()
+ self.chart.legend().setVisible(False)
+ self.chart.setTitle("Nested donuts demo")
+ self.chart.setAnimationOptions(QChart.AllAnimations)
+
+ self.min_size = 0.1
+ self.max_size = 0.9
+ self.donut_count = 5
+
+ self.setup_donuts()
+
+ # create main layout
+ self.main_layout = QGridLayout(self)
+ self.main_layout.addWidget(self.chart_view, 1, 1)
+ self.setLayout(self.main_layout)
+
+ self.update_timer = QTimer(self)
+ self.update_timer.timeout.connect(self.update_rotation)
+ self.update_timer.start(1250)
+
+ def setup_donuts(self):
+ for i in range(self.donut_count):
+ donut = QPieSeries()
+ slccount = randrange(3, 6)
+ for j in range(slccount):
+ value = randrange(100, 200)
+
+ slc = QPieSlice(str(value), value)
+ slc.setLabelVisible(True)
+ slc.setLabelColor(Qt.white)
+ slc.setLabelPosition(QPieSlice.LabelInsideTangential)
+
+ # Connection using an extra parameter for the slot
+ slc.hovered[bool].connect(partial(self.explode_slice, slc=slc))
+
+ donut.append(slc)
+ size = (self.max_size - self.min_size) / self.donut_count
+ donut.setHoleSize(self.min_size + i * size)
+ donut.setPieSize(self.min_size + (i + 1) * size)
+
+ self.donuts.append(donut)
+ self.chart_view.chart().addSeries(donut)
+
+ @Slot()
+ def update_rotation(self):
+ for donut in self.donuts:
+ phase_shift = randrange(-50, 100)
+ donut.setPieStartAngle(donut.pieStartAngle() + phase_shift)
+ donut.setPieEndAngle(donut.pieEndAngle() + phase_shift)
+
+ def explode_slice(self, exploded, slc):
+ if exploded:
+ self.update_timer.stop()
+ slice_startangle = slc.startAngle()
+ slice_endangle = slc.startAngle() + slc.angleSpan()
+
+ donut = slc.series()
+ idx = self.donuts.index(donut)
+ for i in range(idx + 1, len(self.donuts)):
+ self.donuts[i].setPieStartAngle(slice_endangle)
+ self.donuts[i].setPieEndAngle(360 + slice_startangle)
+ else:
+ for donut in self.donuts:
+ donut.setPieStartAngle(0)
+ donut.setPieEndAngle(360)
+
+ self.update_timer.start()
+
+ slc.setExploded(exploded)
+
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+ w = Widget()
+ w.show()
+ sys.exit(app.exec())
diff --git a/examples/charts/nesteddonuts/nesteddonuts.pyproject b/examples/charts/nesteddonuts/nesteddonuts.pyproject
new file mode 100644
index 000000000..69653ae73
--- /dev/null
+++ b/examples/charts/nesteddonuts/nesteddonuts.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["nesteddonuts.py"]
+}
diff --git a/examples/charts/percentbarchart.py b/examples/charts/percentbarchart.py
deleted file mode 100644
index 256070e7f..000000000
--- a/examples/charts/percentbarchart.py
+++ /dev/null
@@ -1,98 +0,0 @@
-
-#############################################################################
-##
-## Copyright (C) 2018 The Qt Company Ltd.
-## Contact: http://www.qt.io/licensing/
-##
-## This file is part of the Qt for Python examples of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:BSD$
-## You may use this file under the terms of the BSD license as follows:
-##
-## "Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions are
-## met:
-## * Redistributions of source code must retain the above copyright
-## notice, this list of conditions and the following disclaimer.
-## * Redistributions in binary form must reproduce the above copyright
-## notice, this list of conditions and the following disclaimer in
-## the documentation and/or other materials provided with the
-## distribution.
-## * Neither the name of The Qt Company Ltd nor the names of its
-## contributors may be used to endorse or promote products derived
-## from this software without specific prior written permission.
-##
-##
-## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-"""PySide2 port of the Percent Bar Chart example from Qt v5.x"""
-
-import sys
-from PySide2.QtCore import Qt
-from PySide2.QtGui import QPainter
-from PySide2.QtWidgets import (QMainWindow, QApplication)
-from PySide2.QtCharts import QtCharts
-
-class MainWindow(QMainWindow):
- def __init__(self):
- QMainWindow.__init__(self)
-
- set0 = QtCharts.QBarSet("Jane")
- set1 = QtCharts.QBarSet("John")
- set2 = QtCharts.QBarSet("Axel")
- set3 = QtCharts.QBarSet("Mary")
- set4 = QtCharts.QBarSet("Samantha")
-
- set0.append([1, 2, 3, 4, 5, 6])
- set1.append([5, 0, 0, 4, 0, 7])
- set2.append([3, 5, 8, 13, 8, 5])
- set3.append([5, 6, 7, 3, 4, 5])
- set4.append([9, 7, 5, 3, 1, 2])
-
- series = QtCharts.QPercentBarSeries()
- series.append(set0)
- series.append(set1)
- series.append(set2)
- series.append(set3)
- series.append(set4)
-
- chart = QtCharts.QChart()
- chart.addSeries(series)
- chart.setTitle("Simple percentbarchart example")
- chart.setAnimationOptions(QtCharts.QChart.SeriesAnimations)
-
- categories = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
- axis = QtCharts.QBarCategoryAxis()
- axis.append(categories)
- chart.createDefaultAxes()
- chart.setAxisX(axis, series)
-
- chart.legend().setVisible(True)
- chart.legend().setAlignment(Qt.AlignBottom)
-
- chart_view = QtCharts.QChartView(chart)
- chart_view.setRenderHint(QPainter.Antialiasing)
-
- self.setCentralWidget(chart_view)
-
-
-if __name__ == "__main__":
- app = QApplication(sys.argv)
- w = MainWindow()
- w.resize(420, 300)
- w.show()
- sys.exit(app.exec_())
diff --git a/examples/charts/percentbarchart/doc/percentbarchart.png b/examples/charts/percentbarchart/doc/percentbarchart.png
new file mode 100644
index 000000000..2f254df1b
--- /dev/null
+++ b/examples/charts/percentbarchart/doc/percentbarchart.png
Binary files differ
diff --git a/examples/charts/percentbarchart/doc/percentbarchart.rst b/examples/charts/percentbarchart/doc/percentbarchart.rst
new file mode 100644
index 000000000..abf631f4f
--- /dev/null
+++ b/examples/charts/percentbarchart/doc/percentbarchart.rst
@@ -0,0 +1,17 @@
+Percent Bar Chart Example
+=========================
+
+The example shows how to create a simple percent bar chart.
+
+A percent bar chart shows the data in sets as a percentage of all sets per
+category.
+
+Creating percent bar charts is just like creating a regular bar chart, except
+that for a percent bar charts, we use the QPercentBarSeries API instead of
+QBarSeries. Also, in the bar chart, we used the nice numbers algorithm to make
+the y-axis numbering look better. With the percent bar chart there is no need
+for that, because the maximum y-axis value is always 100.
+
+.. image:: percentbarchart.png
+ :width: 400
+ :alt: Percent Bar Chart Screenshot
diff --git a/examples/charts/percentbarchart/percentbarchart.py b/examples/charts/percentbarchart/percentbarchart.py
new file mode 100644
index 000000000..9f70c0328
--- /dev/null
+++ b/examples/charts/percentbarchart/percentbarchart.py
@@ -0,0 +1,63 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the Percent Bar Chart example from Qt v5.x"""
+
+import sys
+from PySide6.QtCore import Qt
+from PySide6.QtGui import QPainter
+from PySide6.QtWidgets import (QMainWindow, QApplication)
+from PySide6.QtCharts import (QBarCategoryAxis, QBarSet, QChart, QChartView,
+ QPercentBarSeries)
+
+
+class MainWindow(QMainWindow):
+ def __init__(self):
+ super().__init__()
+
+ set0 = QBarSet("Jane")
+ set1 = QBarSet("John")
+ set2 = QBarSet("Axel")
+ set3 = QBarSet("Mary")
+ set4 = QBarSet("Samantha")
+
+ set0.append([1, 2, 3, 4, 5, 6])
+ set1.append([5, 0, 0, 4, 0, 7])
+ set2.append([3, 5, 8, 13, 8, 5])
+ set3.append([5, 6, 7, 3, 4, 5])
+ set4.append([9, 7, 5, 3, 1, 2])
+
+ series = QPercentBarSeries()
+ series.append(set0)
+ series.append(set1)
+ series.append(set2)
+ series.append(set3)
+ series.append(set4)
+
+ chart = QChart()
+ chart.addSeries(series)
+ chart.setTitle("Simple percentbarchart example")
+ chart.setAnimationOptions(QChart.SeriesAnimations)
+
+ categories = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
+ axis = QBarCategoryAxis()
+ axis.append(categories)
+ chart.createDefaultAxes()
+ chart.addAxis(axis, Qt.AlignBottom)
+ series.attachAxis(axis)
+
+ chart.legend().setVisible(True)
+ chart.legend().setAlignment(Qt.AlignBottom)
+
+ chart_view = QChartView(chart)
+ chart_view.setRenderHint(QPainter.Antialiasing)
+
+ self.setCentralWidget(chart_view)
+
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+ w = MainWindow()
+ w.resize(420, 300)
+ w.show()
+ sys.exit(app.exec())
diff --git a/examples/charts/percentbarchart/percentbarchart.pyproject b/examples/charts/percentbarchart/percentbarchart.pyproject
new file mode 100644
index 000000000..0cf3778af
--- /dev/null
+++ b/examples/charts/percentbarchart/percentbarchart.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["percentbarchart.py"]
+}
diff --git a/examples/charts/piechart/doc/piechart.png b/examples/charts/piechart/doc/piechart.png
new file mode 100644
index 000000000..3f3942c0f
--- /dev/null
+++ b/examples/charts/piechart/doc/piechart.png
Binary files differ
diff --git a/examples/charts/piechart/doc/piechart.rst b/examples/charts/piechart/doc/piechart.rst
new file mode 100644
index 000000000..ad60abc68
--- /dev/null
+++ b/examples/charts/piechart/doc/piechart.rst
@@ -0,0 +1,8 @@
+Pie Chart Example
+=================
+
+The example shows how to create a simple pie chart and do some customizations to a pie slice.
+
+.. image:: piechart.png
+ :width: 400
+ :alt: Pie Chart Screenshot
diff --git a/examples/charts/piechart/piechart.py b/examples/charts/piechart/piechart.py
new file mode 100644
index 000000000..e71359a98
--- /dev/null
+++ b/examples/charts/piechart/piechart.py
@@ -0,0 +1,50 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the Pie Chart Example from Qt v5.x"""
+
+import sys
+from PySide6.QtCore import Qt
+from PySide6.QtGui import QPainter, QPen
+from PySide6.QtWidgets import QMainWindow, QApplication
+from PySide6.QtCharts import QChart, QChartView, QPieSeries
+
+
+class TestChart(QMainWindow):
+
+ def __init__(self):
+ super().__init__()
+
+ self.series = QPieSeries()
+
+ self.series.append('Jane', 1)
+ self.series.append('Joe', 2)
+ self.series.append('Andy', 3)
+ self.series.append('Barbara', 4)
+ self.series.append('Axel', 5)
+
+ self.slice = self.series.slices()[1]
+ self.slice.setExploded()
+ self.slice.setLabelVisible()
+ self.slice.setPen(QPen(Qt.darkGreen, 2))
+ self.slice.setBrush(Qt.green)
+
+ self.chart = QChart()
+ self.chart.addSeries(self.series)
+ self.chart.setTitle('Simple piechart example')
+ self.chart.legend().hide()
+
+ self._chart_view = QChartView(self.chart)
+ self._chart_view.setRenderHint(QPainter.Antialiasing)
+
+ self.setCentralWidget(self._chart_view)
+
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+
+ window = TestChart()
+ window.show()
+ window.resize(440, 300)
+
+ sys.exit(app.exec())
diff --git a/examples/charts/piechart/piechart.pyproject b/examples/charts/piechart/piechart.pyproject
new file mode 100644
index 000000000..2578b435e
--- /dev/null
+++ b/examples/charts/piechart/piechart.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["piechart.py"]
+}
diff --git a/examples/charts/pointconfiguration/chartwindow.py b/examples/charts/pointconfiguration/chartwindow.py
new file mode 100644
index 000000000..36b10aa16
--- /dev/null
+++ b/examples/charts/pointconfiguration/chartwindow.py
@@ -0,0 +1,156 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the Selected Point Configuration Example from Qt 6.5"""
+from PySide6.QtCore import QPointF, Slot
+from PySide6.QtGui import QColor, QIcon, QPainter
+from PySide6.QtWidgets import QMainWindow, QLineEdit, QLabel, QComboBox
+from PySide6.QtWidgets import QCheckBox, QWidget, QGridLayout, QHBoxLayout
+from PySide6.QtCharts import QLineSeries, QXYSeries, QChart, QChartView
+from typing import Union
+
+
+PointConfig = QXYSeries.PointConfiguration
+
+
+class ChartWindow(QMainWindow):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ self.setWindowTitle("Chart")
+ self._series = QLineSeries(self)
+ self._series.setName("Customized series")
+ self._series.setPointsVisible(True)
+ self._series.append([QPointF(0, 7), QPointF(2, 4),
+ QPointF(3, 5), QPointF(7, 4),
+ QPointF(10, 5), QPointF(11, 1),
+ QPointF(13, 3), QPointF(17, 6),
+ QPointF(18, 3), QPointF(20, 2)])
+
+ selected_point_index_label = QLabel("Selected Point: ")
+ self._selected_point_index_lineedit = QLineEdit()
+ self._selected_point_index_lineedit.setReadOnly(True)
+ self._selected_point_index_lineedit.setStyleSheet(
+ "background-color: rgba(0, 0, 0, 0); border: 0px")
+
+ color_label = QLabel("Color: ")
+ self._color_combobox = QComboBox()
+ color_strings = ["red", "orange", "yellow", "green", "blue",
+ "indigo", "violet", "black"]
+ for color_str in color_strings:
+ self._color_combobox.addItem(QIcon(), color_str, QColor(color_str))
+
+ size_label = QLabel("Size: ")
+ self._size_combobox = QComboBox()
+ for size in [2, 3, 4, 6, 8, 10, 12, 15]:
+ self._size_combobox.addItem(QIcon(), str(size), size)
+
+ label_visibility_label = QLabel("Label Visibility: ")
+ self._label_visibility_checkbox = QCheckBox()
+
+ custom_label_label = QLabel("Custom Label: ")
+ self._custom_label_lineedit = QLineEdit()
+
+ self._series.clicked.connect(self._select_point)
+ self._color_combobox.activated.connect(self._set_color)
+ self._size_combobox.activated.connect(self._set_size)
+ label_vis_checkbox = self._label_visibility_checkbox
+ label_vis_checkbox.clicked.connect(self._set_label_visibility)
+ clabel_lineedit = self._custom_label_lineedit
+ clabel_lineedit.editingFinished.connect(self._set_custom_label)
+
+ self._chart = QChart()
+ self._chart.addSeries(self._series)
+ self._chart.createDefaultAxes()
+
+ chart_view = QChartView(self._chart)
+ chart_view.setRenderHint(QPainter.RenderHint.Antialiasing)
+
+ control_widget = QWidget(self)
+ control_layout = QGridLayout(control_widget)
+ control_layout.setColumnStretch(1, 1)
+
+ control_layout.addWidget(selected_point_index_label, 0, 0)
+ control_layout.addWidget(self._selected_point_index_lineedit, 0, 1)
+
+ control_layout.addWidget(color_label, 1, 0)
+ control_layout.addWidget(self._color_combobox, 1, 1)
+
+ control_layout.addWidget(size_label, 2, 0)
+ control_layout.addWidget(self._size_combobox, 2, 1)
+
+ control_layout.addWidget(label_visibility_label, 3, 0)
+ control_layout.addWidget(self._label_visibility_checkbox, 3, 1, 1, 2)
+
+ control_layout.addWidget(custom_label_label, 4, 0)
+ control_layout.addWidget(self._custom_label_lineedit, 4, 1)
+
+ main_widget = QWidget(self)
+ main_layout = QHBoxLayout(main_widget)
+ main_layout.addWidget(chart_view)
+ main_layout.setStretch(0, 1)
+ main_layout.addWidget(control_widget)
+ self.setCentralWidget(main_widget)
+
+ self._select_point(4)
+
+ @Slot(QPointF)
+ def _select_point(self, point: Union[QPointF, int]):
+ try:
+ index = (self._series.points().index(point.toPoint()) if
+ isinstance(point, QPointF) else point)
+ except ValueError:
+ # Do nothing if the place that was clicked on wasn't a point.
+ return
+
+ self._series.deselectAllPoints()
+ self._series.selectPoint(index)
+ self._selectedPointIndex = index
+ self._selectedPointConfig = self._series.pointConfiguration(index)
+ selected_point = self._series.at(index)
+ selected_index_lineedit = self._selected_point_index_lineedit
+ selected_index_lineedit.setText("(" + str(selected_point.x()) + ", "
+ + str(selected_point.y()) + ")")
+ config = self._series.pointConfiguration(index)
+
+ color = config.get(PointConfig.Color) or self._series.color()
+ size = config.get(PointConfig.Size) or self._series.markerSize()
+ labelVisibility = (config.get(PointConfig.LabelVisibility)
+ or self._series.pointLabelsVisible())
+ customLabel = config.get(PointConfig.LabelFormat) or ""
+
+ combobox_value_list = [
+ (self._color_combobox, color.name(), color),
+ (self._size_combobox, str(size), size)
+ ]
+ for box, value_str, value in combobox_value_list:
+ if box.findData(value) < 0:
+ box.addItem(value_str, value)
+ box.setCurrentIndex(box.findData(value))
+
+ self._label_visibility_checkbox.setChecked(labelVisibility)
+ self._custom_label_lineedit.setText(customLabel)
+
+ @Slot(int)
+ def _set_color(self, index: int):
+ spc = self._selectedPointConfig
+ spc[PointConfig.Color] = self._color_combobox.currentData()
+ self._series.setPointConfiguration(self._selectedPointIndex, spc)
+
+ @Slot(int)
+ def _set_size(self, index: int):
+ spc = self._selectedPointConfig
+ spc[PointConfig.Size] = self._size_combobox.currentData()
+ self._series.setPointConfiguration(self._selectedPointIndex, spc)
+
+ @Slot(bool)
+ def _set_label_visibility(self, checked: bool):
+ spc = self._selectedPointConfig
+ spc[PointConfig.LabelVisibility] = checked
+ self._series.setPointConfiguration(self._selectedPointIndex, spc)
+
+ @Slot()
+ def _set_custom_label(self):
+ spc = self._selectedPointConfig
+ spc[PointConfig.LabelFormat] = self._custom_label_lineedit.text()
+ self._series.setPointConfiguration(self._selectedPointIndex, spc)
diff --git a/examples/charts/pointconfiguration/doc/pointconfiguration.png b/examples/charts/pointconfiguration/doc/pointconfiguration.png
new file mode 100644
index 000000000..791698587
--- /dev/null
+++ b/examples/charts/pointconfiguration/doc/pointconfiguration.png
Binary files differ
diff --git a/examples/charts/pointconfiguration/doc/pointconfiguration.rst b/examples/charts/pointconfiguration/doc/pointconfiguration.rst
new file mode 100644
index 000000000..ffe865d5e
--- /dev/null
+++ b/examples/charts/pointconfiguration/doc/pointconfiguration.rst
@@ -0,0 +1,144 @@
+.. role:: py(code)
+ :language: python
+
+Selected Point Configuration Example
+====================================
+
+This example shows how to configure individual points of a :py:`QLineSeries`.
+
+.. image:: pointconfiguration.png
+ :width: 90%
+ :align: center
+ :alt: Line chart with controls for configuring selected points
+
+Features demonstrated
+~~~~~~~~~~~~~~~~~~~~~
+
+In this application you will learn how to:
+
+* Select a series of points on click
+* Override the configuration for the following properties of specific points:
+
+ * Color
+ * Size
+ * Label visibility
+ * Text format of the label
+
+Subclass QMainWindow
+~~~~~~~~~~~~~~~~~~~~
+
+Create a subclass of :py:`QMainWindow` to contain the chart and controls.
+
+.. literalinclude:: chartwindow.py
+ :linenos:
+ :lineno-start: 16
+ :lines: 16-18
+
+Create a line series
+~~~~~~~~~~~~~~~~~~~~
+
+Create a :py:`QLineSeries` containing the points to plot. Give it a name and make the points
+visible.
+
+.. literalinclude:: chartwindow.py
+ :linenos:
+ :lineno-start: 20
+ :lines: 20-28
+
+Create the point configuration controls
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Now, create controls to configure the color, size, and label visibility attributes of a point.
+
+#. Create an associated label for each control, so the user knows what the control does.
+#. For the color and size, use a :py:`QComboBox`, populating it with a variety of colors and size
+ choices.
+#. Create the final two controls. Create a :py:`QCheckbox` to control the visibility of the selected
+ point, and a :py:`QLineEdit` to allow the user to provide a custom label for it.
+
+.. note::
+ Do not set initial values for any of the controls, as a point will always be selected showing
+ its current settings.
+
+.. literalinclude:: chartwindow.py
+ :linenos:
+ :lineno-start: 31
+ :lines: 31-52
+
+Populate the controls upon selecting a point
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Add the logic to set the current control values depending on the chosen point. Note that the whole
+series value is used if there is no customization for a selected point. In this case, if the series
+is set to show blue points, a blue color value will be shown in the color combobox.
+
+Perform some actions upon clicking on the lineseries. Look up the point clicked on and remove the
+prior point selection. Finally, select the point that was clicked on. This makes the point larger to
+indicate its selection. The current selected point's index and :py:`PointConfigurations` are saved
+to a member variable for later use.
+
+Query the :py:`PointConfigurations`, and use those to find the matching indices in the combo boxes.
+Set the current indices of the comboboxes to the corresponding values you looked up. Similarly,
+look up the values in :py:`PointConfigurations`, and update the checkbox and line edit controls.
+
+.. literalinclude:: chartwindow.py
+ :linenos:
+ :lineno-start: 54
+ :lines: 54
+.. literalinclude:: chartwindow.py
+ :linenos:
+ :lineno-start: 97
+ :lines: 97-132
+
+Provide the logic to configure the selected point
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Now that the controls are populated with some values, add logic to do something when the value
+changes. Connect the control signals and the logic, to configure the selected point based on the
+chosen values in the controls. You can do this by setting the :py:`QXYSeries::PointConfiguration`
+value that is associated with the control, to the :py:`m_selectedPointConfig` and
+:py:`PointConfigurations` member variables, and call :py:`QXYSeries::setPointConfiguration`.
+
+.. literalinclude:: chartwindow.py
+ :linenos:
+ :lineno-start: 55
+ :lines: 55-60
+.. literalinclude:: chartwindow.py
+ :linenos:
+ :lineno-start: 140
+ :lines: 140-156
+
+Create the chart and lay out the controls
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Finally, create the chart and its view, add the series to the chart, create the layout of the
+window, and select an initial point.
+
+.. literalinclude:: chartwindow.py
+ :linenos:
+ :lineno-start: 62
+ :lines: 62-95
+
+In our entrypoint file `pointconfiguration.py`, instantiate the :py:`ChartWindow`, resize it, show
+it, and start the event loop.
+
+.. literalinclude:: pointconfiguration.py
+ :linenos:
+ :lineno-start: 11
+ :lines: 11-17
+
+You now have a fully functioning application that demonstrates how to customize individual chart
+points.
+
+Usage
+-----
+To use this example, click any point you'd like to customize, change any of the comboboxes and
+checkboxes controlling the individual point color, size, label visibility. You can customize the
+label text in the line edit at the bottom.
+
+There are three special formatting strings for the label that you can use: ``@pointX``, ``@pointY``,
+and ``@index``. These are replaced with the x value, y value, and index of the point, respectively.
+More information about that can be found in the documentation for
+`QtCharts.QXYSeries.pointLabelsFormat`_.
+
+.. _`QtCharts.QXYSeries.pointLabelsFormat`: https://doc.qt.io/qtforpython/PySide6/QtCharts/QXYSeries.html#PySide6.QtCharts.PySide6.QtCharts.QXYSeries.pointLabelsFormat
diff --git a/examples/charts/pointconfiguration/pointconfiguration.py b/examples/charts/pointconfiguration/pointconfiguration.py
new file mode 100644
index 000000000..d8c90d2df
--- /dev/null
+++ b/examples/charts/pointconfiguration/pointconfiguration.py
@@ -0,0 +1,17 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the Light Markers Points Selection example from Qt v6.2"""
+import sys
+from PySide6.QtWidgets import QApplication
+
+from chartwindow import ChartWindow
+
+
+if __name__ == "__main__":
+
+ a = QApplication(sys.argv)
+ main_window = ChartWindow()
+ main_window.resize(640, 480)
+ main_window.show()
+ sys.exit(a.exec())
diff --git a/examples/charts/pointconfiguration/pointconfiguration.pyproject b/examples/charts/pointconfiguration/pointconfiguration.pyproject
new file mode 100644
index 000000000..c53d798be
--- /dev/null
+++ b/examples/charts/pointconfiguration/pointconfiguration.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["pointconfiguration.py", "chartwindow.py"]
+}
diff --git a/examples/charts/pointselectionandmarkers/doc/pointselectionandmarkers.png b/examples/charts/pointselectionandmarkers/doc/pointselectionandmarkers.png
new file mode 100644
index 000000000..209bc3b0d
--- /dev/null
+++ b/examples/charts/pointselectionandmarkers/doc/pointselectionandmarkers.png
Binary files differ
diff --git a/examples/charts/pointselectionandmarkers/doc/pointselectionandmarkers.rst b/examples/charts/pointselectionandmarkers/doc/pointselectionandmarkers.rst
new file mode 100644
index 000000000..e8776daf8
--- /dev/null
+++ b/examples/charts/pointselectionandmarkers/doc/pointselectionandmarkers.rst
@@ -0,0 +1,72 @@
+.. role:: py(code)
+ :language: python
+
+Light Markers and Points Selection Example
+==========================================
+
+The Light Markers and Points Selection example shows how to use light markers
+and point selections in a series.
+
+.. image:: pointselectionandmarkers.png
+ :width: 90%
+ :align: center
+ :alt: QChart with Light Markers shown
+
+Creating the chart and its elements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+We start by creating a series, filling it with the data, and enabling the light marker and point selection features.
+It is important not to set points visibility to :py:`True`, because light markers functionality is an independent feature and setting both would result in undesired behavior.
+
+.. literalinclude:: pointselectionandmarkers.py
+ :linenos:
+ :lineno-start: 20
+ :lines: 20-42
+ :emphasize-lines: 2-12
+
+Then we create the :py:`QChart`, the :py:`QChartview` and the control widget with its layout to arrange customization elements.
+
+.. literalinclude:: pointselectionandmarkers.py
+ :lineno-start: 44
+ :lines: 44-53
+ :emphasize-lines: 1,6,9
+
+Creating UI for configuring the chart
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The next step is where we create user interface elements that allow customizing the chart, including setting light marker and selection marker images.
+
+.. literalinclude:: pointselectionandmarkers.py
+ :linenos:
+ :lineno-start: 54
+ :lines: 54-57
+
+We create the label for the marker selection combobox and fill the combobox with the items. We then provide functionality to the combobox, allowing the user's selection to set the desired light marker image. As light markers are enabled and disabled by setting a valid QImage or setting an empty :py:`QImage()`, we need to make sure that if the user does not wish unselected points to be displayed, we do not actually set the light marker image.
+If checking isn't performed, a new :py:`QImage` will be set as the light marker and unselected points will be visible even though it has been switched off.
+
+.. literalinclude:: pointselectionandmarkers.py
+ :linenos:
+ :lineno-start: 59
+ :lines: 59-67
+ :emphasize-lines: 1-3
+
+Almost the same procedure applies to the selected point light marker and line color. The only difference is that there is no need to check the visibility of unselected points as it doesn't affect the functionality.
+
+.. literalinclude:: pointselectionandmarkers.py
+ :linenos:
+ :lineno-start: 70
+ :lines: 70-85
+
+A small difference comes with changing visibility of unselected points. As it was mentioned before, making light markers invisible is achieved by setting the light marker to an empty :py:`QImage()`. That is why, depending on checkbox state, selected point light marker is set to an empty :py:`QImage` or to the light marker extracted from the current index of the corresponding combobox.
+
+.. literalinclude:: pointselectionandmarkers.py
+ :linenos:
+ :lineno-start: 88
+ :lines: 88-97
+ :emphasize-lines: 5-6
+
+The final part is to lay out the widgets within the main widget and set the main window size.
+
+Usage
+-----
+To use this example, change any of the comboboxes and checkboxes controlling the markers, line color, and unselected point visibility on the right. Then try clicking on points in the chart to select or deselect them.
diff --git a/examples/charts/pointselectionandmarkers/images/blue_triangle.png b/examples/charts/pointselectionandmarkers/images/blue_triangle.png
new file mode 100644
index 000000000..7790453c8
--- /dev/null
+++ b/examples/charts/pointselectionandmarkers/images/blue_triangle.png
Binary files differ
diff --git a/examples/charts/pointselectionandmarkers/images/green_triangle.png b/examples/charts/pointselectionandmarkers/images/green_triangle.png
new file mode 100644
index 000000000..29ae043f2
--- /dev/null
+++ b/examples/charts/pointselectionandmarkers/images/green_triangle.png
Binary files differ
diff --git a/examples/charts/pointselectionandmarkers/markers.qrc b/examples/charts/pointselectionandmarkers/markers.qrc
new file mode 100644
index 000000000..eb1e56d19
--- /dev/null
+++ b/examples/charts/pointselectionandmarkers/markers.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/blue_triangle.png</file>
+ <file>images/green_triangle.png</file>
+ </qresource>
+</RCC>
diff --git a/examples/charts/pointselectionandmarkers/pointselectionandmarkers.py b/examples/charts/pointselectionandmarkers/pointselectionandmarkers.py
new file mode 100644
index 000000000..df7b61687
--- /dev/null
+++ b/examples/charts/pointselectionandmarkers/pointselectionandmarkers.py
@@ -0,0 +1,128 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the Light Markers Points Selection example from Qt v6.2"""
+import sys
+
+from PySide6.QtCore import Slot, QPointF, Qt
+from PySide6.QtCharts import QChart, QChartView, QSplineSeries
+from PySide6.QtGui import QPainter, QImage
+from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QGridLayout,
+ QComboBox, QCheckBox, QLabel, QHBoxLayout)
+
+import utilities as Utilities
+
+if __name__ == "__main__":
+
+ a = QApplication(sys.argv)
+ window = QMainWindow()
+ window.setWindowTitle("Light Markers and Points Selection")
+
+ marker_size = 20.
+ series = QSplineSeries()
+ series.append([QPointF(0, 0),
+ QPointF(0.5, 2.27),
+ QPointF(1.5, 2.2),
+ QPointF(3.3, 1.7),
+ QPointF(4.23, 3.1),
+ QPointF(5.3, 2.3),
+ QPointF(6.47, 4.1)])
+ series.setMarkerSize(marker_size)
+ series.setLightMarker(Utilities.default_light_marker(marker_size))
+ series.setSelectedLightMarker(Utilities.default_selected_light_marker(marker_size))
+
+ @Slot(QPointF)
+ def toggle_selection(point):
+ try:
+ index = series.points().index(point)
+ if index != -1:
+ series.toggleSelection([index])
+ except ValueError:
+ pass
+
+ series.clicked.connect(toggle_selection)
+
+ chart = QChart()
+ chart.addSeries(series)
+ chart.createDefaultAxes()
+ chart.legend().setVisible(False)
+
+ chart_view = QChartView(chart)
+ chart_view.setRenderHint(QPainter.Antialiasing)
+
+ control_widget = QWidget(window)
+ control_layout = QGridLayout(control_widget)
+ char_point_combobox = QComboBox()
+ char_point_selected_combobox = QComboBox()
+ line_color_combobox = QComboBox()
+ show_unselected_points_checkbox = QCheckBox()
+
+ @Slot(int)
+ def set_light_marker(index):
+ if show_unselected_points_checkbox.isChecked():
+ series.setLightMarker(Utilities.get_point_representation(
+ Utilities.point_type(index), marker_size))
+
+ char_point = QLabel("Char point: ")
+ char_point_combobox.addItems(["Red rectangle", "Green triangle", "Orange circle"])
+ char_point_combobox.currentIndexChanged.connect(set_light_marker)
+
+ @Slot(int)
+ def set_selected_light_marker(index):
+ series.setSelectedLightMarker(
+ Utilities.get_selected_point_representation(
+ Utilities.selected_point_type(index), marker_size))
+
+ char_point_selected = QLabel("Char point selected: ")
+ char_point_selected_combobox.addItems(["Blue triangle", "Yellow rectangle", "Lavender circle"])
+ char_point_selected_combobox.currentIndexChanged.connect(set_selected_light_marker)
+
+ @Slot(int)
+ def set_line_color(index):
+ series.setColor(Utilities.make_line_color(Utilities.line_color(index)))
+
+ line_color_label = QLabel("Line color: ")
+ line_color_combobox.addItems(["Blue", "Black", "Mint"])
+ line_color_combobox.currentIndexChanged.connect(set_line_color)
+
+ @Slot(int)
+ def display_unselected_points(checkbox_state):
+ if checkbox_state:
+ series.setLightMarker(
+ Utilities.get_point_representation(
+ Utilities.point_type(char_point_combobox.currentIndex()), marker_size))
+ else:
+ series.setLightMarker(QImage())
+
+ show_unselected_points_label = QLabel("Display unselected points: ")
+ show_unselected_points_checkbox.setChecked(True)
+ show_unselected_points_checkbox.stateChanged.connect(display_unselected_points)
+
+ control_label = QLabel("Marker and Selection Controls")
+ control_label.setAlignment(Qt.AlignHCenter)
+ control_label_font = control_label.font()
+ control_label_font.setBold(True)
+ control_label.setFont(control_label_font)
+ control_layout.addWidget(control_label, 0, 0, 1, 2)
+ control_layout.addWidget(char_point, 1, 0)
+ control_layout.addWidget(char_point_combobox, 1, 1)
+
+ control_layout.addWidget(char_point_selected, 2, 0)
+ control_layout.addWidget(char_point_selected_combobox, 2, 1)
+
+ control_layout.addWidget(line_color_label, 3, 0)
+ control_layout.addWidget(line_color_combobox, 3, 1)
+
+ control_layout.addWidget(show_unselected_points_label, 4, 0)
+ control_layout.addWidget(show_unselected_points_checkbox, 4, 1, 1, 2)
+ control_layout.setRowStretch(5, 1)
+
+ main_widget = QWidget(window)
+ main_layout = QHBoxLayout(main_widget)
+ main_layout.addWidget(chart_view)
+ main_layout.addWidget(control_widget)
+
+ window.setCentralWidget(main_widget)
+ window.resize(1080, 720)
+ window.show()
+ sys.exit(a.exec())
diff --git a/examples/charts/pointselectionandmarkers/pointselectionandmarkers.pyproject b/examples/charts/pointselectionandmarkers/pointselectionandmarkers.pyproject
new file mode 100644
index 000000000..8c394457c
--- /dev/null
+++ b/examples/charts/pointselectionandmarkers/pointselectionandmarkers.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["pointselectionandmarkers.py", "utilities.py", "markers.qrc"]
+}
diff --git a/examples/charts/pointselectionandmarkers/rc_markers.py b/examples/charts/pointselectionandmarkers/rc_markers.py
new file mode 100644
index 000000000..f5a9cd42b
--- /dev/null
+++ b/examples/charts/pointselectionandmarkers/rc_markers.py
@@ -0,0 +1,275 @@
+# Resource object code (Python 3)
+# Created by: object code
+# Created by: The Resource Compiler for Qt version 6.3.1
+# WARNING! All changes made in this file will be lost!
+
+from PySide6 import QtCore
+
+qt_resource_data = b"\
+\x00\x00\x05m\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x02\x00\x00\x00\x01\xf6\x02\x03\x00\x00\x00{5\xdc\xf0\
+\x00\x00\x00\x09PLTE\x00\x00\x00\x98\xbag\x98\xba\
+g\xb0,\xf9`\x00\x00\x00\x02tRNS\x00\x93\x1f\
+\x95\x0f\xc6\x00\x00\x05\x11IDATx\xda\xdc\xd31\
+\x95\xc4@\x0c\x04\xd1U\x22\x10Bc<Bc\x10N\
+\x5c(\x0fC\xfb\xde\x8c\xe5\xeeX\xc1\x0fT\xbf\x7f.\
+~//\x8f\xdf\xbb\xab\xf3\xf7\xee\xfa\xfa\xbd\xba\xe0\x96\
+\xee\xfd\x00\x09\xd2\x17\xfa\x01\x0a\xa4\x0c\xfc\x00\x0dR\x87\
+v\x80\x00\xa9C?@\x82\xd4\xa1\x1f\xa0@\xea\xd0\x0f\
+\xd0 uh\x07\x08\x90:\xf4\x03$H\x1d\xfa\x01\x0a\
+\xa4\x0e\xfd\x00\x0dR\x87v\x80\x00\xa9C?@\x82\xd4\
+\xa1\x1f\xa0@\xea\xd0\x0f\xd0 uh\x07\x08\x90:\xf4\
+\x03$H\x1d\xfa\x01\x0a\xa4\x0e\xfd\x00\x0dR\x87v\x80\
+\x00\xa9C?@\x82\xd4\xa1\x1f\xa0@\xea\xd0\x0f\xd0 \
+uh\x07\x08\x90:\xf4\x03$H\x1d\xfa\x01\x0a\xa4\x0e\
+\xfd\x00\x0dR\x87v\x80\x00\xa9C?@\x82\xd4\xa1\x1f\
+\xa0@\xea\xd0\x0f\xd0 uh\x07\x08\x90:\xf4\x03$\
+H\x1d\xfa\x01\x0a\xa4\x0e\xfd\x00\x0dR\x87v\x80\x00\xa9\
+C?@\x82\xd4\xa1\x1f\xa0@\xea\xd0\x0f\xd0\xf0n\x87\
+\xcd\xbb\x19\x04#\x01\x1b3\xc8\xa1\x80}\x19\xd4P\xc0\
+\xbe\x0e{(`[\x87\xc1P\xc0\xb6\x0es,`W\
+\x875\x16\xb0\xab\xc3\x1e\x0b\xd8\xd4a0\x16\xb0\xa9\xc3\
+\x1c\x0c\xd8\xd3a\x0d\x06\xec\xe9\xb0\x07\x03\xb6t\x18\x0c\
+\x06l\xe90G\x03vtX\xa3\x01;:\xec\xd1\x80\
+\x0d\x1d\x06\xa3\x01\x1b:\xcc\xe1\x80\xf5\x1d\xd6p\xc0\xfa\
+\x0e{8`y\x87\xc1p\xc0\xf2\x0es<`u\x87\
+5\x1e\xb0\xba\xc3\x1e\x0fX\xdca0\x1e\xb0\xb8\xc3\xfc\
+\x00`m\x87\xf5\x01\xc0\xda\x0e\xfb\x03\x80\xa5\x1d\x06\x1f\
+\x00,\xed0?\x01X\xd9a}\x02\xb0\xb2\xc3\xfe\x04\
+`a\x87\xc1'\x00\x0b;\xcc\x8f\x00\xd6uXo\x03\
+\x1a\xa4\x0e\xed\x00\x01R\x87~\x80\x04\xa9C?@\x81\
+\xd4\xa1\x1f\xa0A\xea\xd0\x0e\x10 u\xe8\x07H\x90:\
+\xf4\x03\x14H\x1d\xfa\x01\x1a\xa4\x0e\xed\x00\x01R\x87~\
+\x80\x04\xa9C?@\x81\xd4\xa1\x1f\xa0A\xea\xd0\x0e\x10\
+(\xbb\x0d\x01\x89\xb4\xc3\x0fPH;\xfd\x00\x8d\xb4\xcb\
+\x0e\x10h\xbb\xed\x00\x89\xb8\xc3\x0dP\x88;\xdd\x00\x8d\
+\xb8\xcb\x0c\x10\xa8\xbb\xcd\x00\x89\xbc\xc3\x0bP\xc8;\xbd\
+\x00\x8d\xbc\xcb\x0a\x10\xe8\xbb\xad\x00\x09\xfa\x0e'@\x81\
+\xbe\xd3\x09\xd0\xa0\xef2\x02\x04Ov\x1b\x01\x92G;\
+|\x00\xc5\xa3\x9d>\x80\xe6\xd1.\x1b@\xf0l\xb7\x0d\
+ y\xb8\xc3\x05P<\xdc\xe9\x02h\x1e\xee2\x01\x04\
+Ow\x9b\x00\x92\xc7;<\x00\xc5\xe3\x9d\x1e\x80\xe6\xf1\
+.\x0b@\xf0|\xb7\x05\xe0\x8f{:(\x82(\x06\x81\
+ Z\xb9 \x22j\xd0\x83\x1aDpaT\xae\x86\xd4\
+\x87,\x93V\xf0.-\xf8\x90\xbe\x00\xd8\xf8\x90\xbf\x00\
+0|(\x1e\x00,|)\x1f\x00\x08>\xa5\xfc\x80\x8d\
+O9?\xc0\xf0\xa9\xa0\x07,|+\xe9\x01\x82\x8f)\
+;`\xe3c\xce\x0e0|,\xc8\x01\x0b_Kr\x80\
+\xe0s\xca\x0d\xd8\xf8\x9cs\x03\x0c\x9f\x0bj\xc0\xc2\xf7\
+\x92\x1a (H\x99\x01\x1b\x0593\xc0PP\x10\x03\
+\x16*Jb\x80\xa0$\xe5\x05l\x94\xe4\xbc\x00CI\
+A\x0bX\xa8)i\x01\x82\xa2\x94\x15\xb0Q\x94\xb3\x02\
+\x0cE\x05)`\xa1\xaa$\x05\x08\xcaRN\xc0FY\
+\xce\x090\x94\x15\x94\x80\x85\xba\x92\x12 (L\x19\x01\
+\x1b\x859#\xc0PX\x10\x02\x16*KB\x80\xa04\
+\xe5\x03l\x94\xe6|\x00CiA\x07X\xa8-\xe9\x00\
+\x82\xe2\x94\x0d\xb0Q\x9c\xb3\x01\x0c\xc5\x05\x19`\xa1\xba\
+$\x03\x08\xcaS.\xc0Fy\xce\x050\x94\x17T\x80\
+\x85\xfa\x92\x0a hH\x99\x00\x1b\x0d9\x13\xc0\xd0P\
+\x10\x01\x16:J\x22\x80\xa0%\xe5\x01l\xb4\xe4<\x00\
+CKA\x03X\xe8)i\x00\x82\xa6\x94\x05\xb0\xd1\x94\
+\xb3\x00\x0cM\x05\x09`\xa1\xab$\x01\x08\xdaR\x0e\xc0\
+F[\xce\x010\xb4\x15\x14\x80\x85\xbe\x92\x02 hL\
+\x19\x00\x1b\x8d9\x03\xc0\xd0X\x10\x00\x16:K\x02\x80\
+\xa05\x9d\x0f\xd8h\xcd\xe7\x03\x0c\xad\xc5x\xc0Bo\
+9\x1e hN\xa7\x036\x9a\xf3\xe9\x00Cs1\x1c\
+\xb0\xd0]\x0e\x07\x08\xda\xd3\xd9\x80\x8d\xf6|6\xc0\xd0\
+^\x8c\x06,\xf4\x97\xa3\x01\x82\x0b\xe9d\xc0\xc6\x85|\
+2\xc0p\xa1\x18\x0cX\xb8Q\x0e\x06\x08\xae\xa4s\x01\
+\x1bW\xf2\xb9\x00\xc3\x95b,`\xe1N9\x16 \xb8\
+\x94N\x05l\x5c\xca\xa7\x02\x0c\x97\x8a\xa1\x80\x85[\xe5\
+P\x80\xe0Z:\x13\xb0q-\x9f\x090\x5c+F\x02\
+\x16\xee\x95#\x01\x82\x8b\xe9D\xc0\xc6\xc5|\x22\xc0p\
+\xb1\x18\x08X\xb8Y\x0e\x04\x08\xae\xa6\xff\x06\xf8\xe1\x85\
+\xef\x01\xe2\xf0\xc2\xf7\x00yx\xe1{\x00\xe8\xe1\x85\xef\
+\x01\xfc\xf0\xc2\xf7\x00qx\xe1{\x80<\xbc\xf0=\x00\
+\xf4\xf0\xc2\xf7\x00~x\xe1{\x808\xbc\xf0=@\x1e\
+^\xf8\x1e\x00zx\xe1{\x00?\xbc\xf0=@\x1c^\
+\xf8\x1e \x0f/|\x0f\x00=\xbc\xf0=\x80\x1f^\xf8\
+\x1e\xe0\xd7=\x1d\x13\x01\x00\xc30\x0c\xa4f\x88\x01\x91\
+%FY\x0c\x9az'\x06\xbf\xfc\xc2\x85>\xc0\xc1\x85\
+>@\x03\x17\xfa\x00\x03\x17\xfa\x00\x0b\x17\xfa\x00\x07\x17\
+\xfa\x00\x0d\x5c\xe8\x03\x0c\x5c\xe8\x03,\x5c\xe8\x03\x1c\x5c\
+\xe8\x034p\xa1\x0f0p\xa1\x0f\xb0p\xa1\x0fpp\
+\xa1\x0f\xd0\xfc]\xd8\xe6\x01\x9f\xda\xf9\x10\xf2\x1c\xc7\xb0\
+\x00\x00\x00\x00IEND\xaeB`\x82\
+\x00\x00\x08\xac\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x01\x00\x00\x00\x00\xfb\x08\x03\x00\x00\x00\xb2\x8e\xba:\
+\x00\x00\x00\x8dPLTE\x00\x00\x00i\xba\xf0i\xba\
+\xf0i\xba\xf0i\xba\xf0i\xba\xf0i\xba\xf0i\xba\xf0\
+i\xba\xf0i\xba\xf0i\xba\xf0i\xba\xf0i\xba\xf0i\
+\xba\xf0i\xba\xf0i\xba\xf0i\xba\xf0i\xba\xf0i\xba\
+\xf0i\xba\xf0i\xba\xf0i\xba\xf0i\xba\xf0i\xba\xf0\
+i\xba\xf0i\xba\xf0i\xba\xf0i\xba\xf0i\xba\xf0i\
+\xba\xf0i\xba\xf0i\xba\xf0i\xba\xf0i\xba\xf0i\xba\
+\xf0i\xba\xf0i\xba\xf0i\xba\xf0i\xba\xf0i\xba\xf0\
+i\xba\xf0i\xba\xf0i\xba\xf0i\xba\xf0i\xba\xf0i\
+\xba\xf0i\xba\xf0\x9c\xb2p\x14\x00\x00\x00.tRN\
+S\x00\x05\xf7\xfb\x19\x13U\x09\xf3\xe2H\x1d\x94z\x0f\
+0\xdf\xc9e\xec\xcd3\x22\xa37\x86\xda\xc0tO\xac\
+\xe5\xb8\x80\xb3k\xe9\x9a\xa7\xc5*\xd4@_\x8e:=\
+\xa4\x0e\xbb\x00\x00\x07\xa0IDATx\xda\xe4\xdd\x07\
+b\xaa@\x10\x80av\x11\x10i\x8a\x82=\xf6\xae{\
+\xff\xe3=\xf2L\x1c\xc0(b\x81e\xe6?\x020\xbb\
+\x9f\x94D)3V\xdbnk.S\xc8\xc6\xc2\xfd\xde\
+\xb3\x5c\x85ll\xef\xf4G\xfa\x96\xee%\xe0\xfa\xc3\xce\
+\xd4\x1e\x1b\x0a\xd5\xc2Y\x93O\xa6\xbe\xa6\xd0\x8ci\xfb\
+U[\x88\xc1,Th\xa6\xf5\x16s.D}\xb5\xd7\
+h\xae\x02\x96\xdf\xdd\xa9B\xf0\xe9\xe2Ds\x08\x02{\
+P\xff>\x00\xbb\xaeOr\x08\x8c\xf1\x9c\x8b(\xb5\xdd\
+9\x06\x0a\xb9\x98\xeb-Z\xe2\x5c}\xde\xa0\xb7\x08\xb0\
+\xadn\x0f\xc4O\x1d\xdf\x22g\x01\xa3\xd1\x1f\xb6\xc5O\
+M[\x0f\xa9]\x03\xae?\x9dp\xf1S{xlP\
+\xbb\x04\xc2\xd9@\x15\xbfq\x93\x1a\x07\xcf\x08\x84Tj\
+\x1c\xd4z\xfe\x9c\x8bK\xf48\x18\x9e\x11\x08E\x1c\xec\
+Q\x1a\x823\x02/\x91\xe3\xa01\x9er\x91Hm\xb7\
+\x8e=\x85H\xcc\xdd\x8e:\xe2\x12=\x0e\x02\x02\x13u\
+\x16\x16\x91#\x00\x08\xfc\x1f=\x0e\x02\x02\xffG\x8f\x83\
+\x09\x04\x0ar\x1cL!\x90\x1e\x07\xb5 \x81@z\x1c\
+\x04\x04^\xa5\x92\xe0 \xf0*\x95\x02\x07\x01\x81\xd7\
+\xa9K\xf4\x1cL#\xf0\x9a\x83c\xdc\x8b\xc07\x02\x9b\
+\xe2\x12=\x0e\x02\x02od\xdac\xd4\x1c\x8c\x10hr\
+q\x89\x1e\x07\x93\x08$\xc7\xc1\x14\x02\xe9q0\x85\xc0\
+[\x1c<\xa1}k(\xf4Wq\x04\xd2\xe3`\xcf\xde\
+\xd5\x05D\x8e\x83I\x04\xde\xe3\xe0IA\x18 0\xab\
+\xfaT\xc78\x03\x06 0\xab\x9d\xe3!\xfcY\x0c\x08\
+\xccl\xd2\xf5=|\x07@\x03\x04fU\xeftu|\
+\xaf\x8ff 0\xf5\x94dd)\xb8\x02\x04>\xd4\xe4\
+\x88m\x06\x00\x81\x0f\xc5\xd7\xe3\x10\xd7o\xa2\xf0\xb0\xda\
+\x89\x1c\xb5\xfa\xe3\x9a\x82)@\xe0C\xa9\xe6t\xe6)\
+\x88b\x80\xc0\xc7\xe2f\x17\xd1\xb3R@\xe0\xe3\xa9\xc3\
+C\x0d\xcd\x11\x00\x04\xe6h0;\xa19\x02\x11\x02\xa7\
+m\x91\xb3\xc9z\x11`\xd9\x08\x22\x046\xb9\xb8D\x8f\
+\x83\x11\x02\xb9\xc8\x9b\xda\xde \xe1`\x0a\x81\xf48\xa8\
+y\x80\xc0\x5c\xf1\xaf1\x8aw\xa8\x01\x81yk\xcd\x1a\
+\x188\x98D`>\x0e:\x088\xc8t@`\xcex\
+\xb3\xfa\x1cL!\x90\x1e\x07S\x08\xa4\xc7A@\xe0S\
+-+\xcfA\xcd\x9f\xc7\x11\x98\x9f\x83\xab\x8as\xf0\x1b\
+\x81\xaax:^q\x0e\xa6\x10H\x8f\x83\xdf\x08\x8c\x9d\
+\x7fz\x1cL\x22\x90 \x07\x01\x81\xcfW\xe5\xbb\x83I\
+\x04\x92\xe3 \xf0\xb5\xd4ME9\x98B =\x0e\
+\xa6\x10\xf8\x0a\x07\xfdJr0\x85@z\x1c\xdc\xf6\x01\
+\x81/\xc5\x97U\xe4\xa0a5\xba\xb1\x01\xa0\xc7\xc1\xda\
+~4\x8c\x9d\x7fz\x1c\xdc\x8e\xbeb[\x00A\x0e\xee\
+\xd7\xf1O\xe3\xe8q\xd0=\xb4\xc4\x1b\xe3\xe6\xbaR\x1c\
+d\xb5S\x7f \xde\x99\xba\xf1\xab\x84!\xa3\xb7XO\
+\xc4%z\x1c\xd4\xf4U\xa7..\xd1\xe3\xa05j\xb5\
+Uq\x89\x1c\x07\x99g'\x06\x80\x1a\x07\x8dP\xff\xe2\
+\xe2\xedM\xec\xaap\xd0j\xcc6\xaax{je8\
+\xe89\xf3\x18\x02\x09r\xb0\x01\x08|kUyX\xec\
+\x1e:\xe2#\xf1f\x158\x08\x08|\x7f\xbc\x0a\x1c\x04\
+\x04~\xa0A_~\x0eF\x08l%\x11H\x8c\x83W\
+\x08\xa4\xc6\xc14\x02\x89q0\x13\x81\xafs0\x90z\
+\x11\xf8\x0b\x81\xa48\xe8\xfd}'\x90\x0e\x07\x1bk\x93\
+\x8b\xab\xe8p\xf0\x16\x02\x89p\xf0c\x08LsP\xd6\
+\x19\xb8\x87@\x12\x1c\xd4t\xfb&\x02Ip\x10\x10\xf8\
+\xd1\xea\xad\x95\xa4\x9f\xd7\xdfF \x09\x0e\x02\x02?\x9e\
+)%\x07\xef#\x90\x00\x07\x01\x81\x9f\xaf\xe5H\xc8\xc1\
+L\x04\x22\xe7\xa0\xebg \x107\x07\x99\xd6\xebg\x0d\
+\x00j\x0e\xba=\xbf\x00\x04&8\xd8\x93\x8a\x83\x80\xc0\
+\x82jK\xc6Ak\xb4Y\xaa\x22+\xc4\x1c\x04\x04\x16\
+\x14\x9f\x0c%\xe2 \xb0\xb8T\x998X\x14\x02\xd3\
+\x1c\xac\xc9\xb2\x0a\xe4A J\x0e\x02\x02\x8b\xcc\x9c;\
+\x92\xfc\x8f\xb6\x5c\x08\xc4\xc7\xc1\x9c\x08\xc4\xc7\xc1o\x04\
+.E\xb1\x01\x07%\xf8\xbb\x83\x80\xc0\xc2kw\x0f^\
+\xf9\x1b\x81\xe5\x14\x88\xc04\x07m\x098\xe8\xd9%\x0c\
+\x00p0T\xca\xcd\xb0\xf2\x22\x10\x19\x07#\x04\xb6J\
+\x19\x00\xe0`\xb9G (\x1c\x81i\x0e\xee\xcb\xdd\x0a\
+\x1b\xeb'>\x8dC\xc4\xc12\x10\x98\xe6\xe08\xe7\x0c\
+\xa0@ \xc4[\x8b\xf2f\xc0\x0d\xfc\xeeR\x94\x5c3\
+/\x07q P\x0e\x0e>\x8d@,\x1c\xf4\xec\xd2\x07\
+\xa0\x14\x0e\x02\x02\xe7\x5c\x94_\xc4\xc1\x1eS\x0a\x0d\x10\
+(dH\x9d?\xceAL\x08,\x9d\x83\x11\x02e\x98\
+\x80|\x1c\xc4\x84\xc08\x07\xbf\x1e\xe3 2\x04\x96\xca\
+A78\x94\x8f\xc0R8\x08\x08\xdc\x94\x8e\xc0\xbc\x1c\
+D\x87\xc029\xe8\xad$\x1a\x80\xff\x1ct\xb28\x88\
+\x11\x81y8\x88\x13\x81y8\x88\x13\x81P\xa7H\x0e\
+\x8e\xd7\x03\x89\xb6\x80\xe29\xa8\xc9\x83@\xa8~\x97\x83\
+x\x11\xf80\x07\xd1\x22\xb0x\x0e\xd6\xf4\xa3L\x08|\
+\x90\x83x\x11X<\x07\x03\xb9\x10\xf8\x10\x07Q#0\
+\xc9A\xe5\xaf\x90#0\x9b\x83\xd8\x11X$\x07\x99\x8c\
+\x08,\x92\x83\xda\xa2#\xe5\x0eP\x10\x07\x99\x16H\x89\
+\xc0\xc28\xe8z\x92\x22\xf0\x1e\x07I \xb0(\x0eZ\
+\xcep\x22\xf3\x12\xf0'\x07I \xf0\xd3\x1c\x04\x04J\
+~\xfe\xaf\xef\x0e\x92A`\x9c\x83\xfag8\xc8zR\
+#\xf0\x06\x07\xe9 \xf0o\x0e\x12B\xe0\xa79\xc8\xdc\
+\xa0o\x8aj\x04\x1c|3\x02\xdb\xa2\x22\xfdr\x90\x18\
+\x02?\xcb\xc1P~\x04B\xfc\xccAj\x08\xfc$\x07\
+Y%\x10\x08\x16R\xcdU\xef\xdd\x08\x94\xf0iX\x16\
+\x07\x09\x220\xc9A\x82\x08Lr\x90 \x02\xa1\xfa \
+\xe2 A\x04&9H\x11\x81)\x0e\xd2C`\x8a\x83\
+\xf4\x10\x08\xf1\xd6Q\xd7\xe8!\xf0\xfd\x1cd5}Z\
+\xc1\xf3\x1f\xc5\xcd\xd5\x89\x11D`\x8a\x83\x04\x11\xf8^\
+\x0e\xb2q\xb7j\x08\x84\xcc/' \x88\xc0\x14\x07\x09\
+\x220\xc9A\x8a\x08\x8cs0p\xd9+\x08\x1c\xf7\xab\
+\x88\xc0\x04\x07\xb7\x06=\x04&9X\xa3\x87\xc0\x14\x07\
+\x09\x220\xc9A\x8a\x08\x84\xd4i\xc4A\x82\x08|\x89\
+\x83\x80\xc0]\xa5\xb7\x80_\x0e\x8e\x82\xa7\x11(\xeb[\
+\xc199\xa83\x82\x08Lr\x90\x22\x02!\x138\x98\
+\x13\x81\x18& \xaa\xbe\xd6\xb7.=\x04\xbe\xca\xc1`\
+\x85d\x00~8H\x10\x81I\x0e2\x82\x08|\x8a\x83\
+\x80@\x1c{\xe0\x93\x1c4p 0\xc9A\x82\x08\x8c\
+sp\xad\xb3\x1c\x08\xf4\x90 \xf0\x92\x9a\x8b\x83\xeeV\
+\xc7\x82\xc0\x9c\x1c\x04\x04\x0eqM@T\xbd\xabo\x0d\
+z\x08\x84\xf8\xe6q\x0e\xf6d\xff2\xea\x99Ts\xe8\
+l\x1fF\xa0\xc0\x97\xfa\xe8\xddA\x86\x0c\x81)\x0e\x12\
+D \xb4\x8b8\xc8\xe8!\x10\x9a\xcc\x9d\x13\xa3\x87@\
+\x88O\xa6\x07#k\x00\x0ct\x08\x8c\xa5\xee\x9c\x90\x22\
+\x02\xa1\xa5\xbd\xaf\x19\xf4\x10\x08\xf1\xf9\xe2\xa4\xd1C`\
+|\x06\xd6\xbeu\x1f\x81\x98\x07@\x08\xb5>\xb0\xbd\xfb\
+\x08\x1c\x0a\xdc\xd5\xbf\x1a\x06A\x04\xc6\xda,<\x8d \
+\x02\xa1\x81\xado\xd9-\x04\xeah\x11\x08\xb5\x87\xc7=\
+\xbb\x83@\xc4[\xc09\xbe\x1c\x1e\x0c\x82\x08\x8c5p\
+B\x8a\x08Lr\x90\xd1C\xe0\x1d\x0e\x02\x02M\xf4+\
+\xc0\x99\x83]\xdf\xa2\x87\xc0,\x0e2\x0d=\x02!>\
+o\x18\x7f p'\xc8\xf4\xcdA\x82\x08\xfcW\x9e\x1d\
+\xa3\x00\x08\x03A\x14]\x95\x10Q\x12Q,D,\x84\
+46z\xff\xe3i\xaau\xd6\xca63\x97\xf8\x0f\xc6\
+p\x90\x0f\x81\xc0\xc1\xae\xb2\x08l)\x12\xa0\x1c\x8c\xf2\
+\x1a\x0b\x02\x81\x83\x8c\x084\x1c\xe4C pp\xd1\x10\
+\x1ca\xe7@\xa0\xe1`\xd9w\xf0\x0f\x0e2!\x109\
+\xc8\x88@\xdd\x98\x86(\xcf\xfcI\x85\xc0/\x07\x1d\x17\
+\x02\x91\x83>7p\xa3B pp\xca%\xec\xc3z\
+Q\xae\xa9\xe7\xe4\xe4\x06\xc7Z\x00\x1d\x81h\xe2\xc4\x00\
+\x00\x00\x00IEND\xaeB`\x82\
+"
+
+qt_resource_name = b"\
+\x00\x06\
+\x07\x03}\xc3\
+\x00i\
+\x00m\x00a\x00g\x00e\x00s\
+\x00\x12\
+\x0c\xf7v\xe7\
+\x00g\
+\x00r\x00e\x00e\x00n\x00_\x00t\x00r\x00i\x00a\x00n\x00g\x00l\x00e\x00.\x00p\x00n\
+\x00g\
+\x00\x11\
+\x02\xf5Q\x07\
+\x00b\
+\x00l\x00u\x00e\x00_\x00t\x00r\x00i\x00a\x00n\x00g\x00l\x00e\x00.\x00p\x00n\x00g\
+\
+"
+
+qt_resource_struct = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x02\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00<\x00\x00\x00\x00\x00\x01\x00\x00\x05q\
+\x00\x00\x01\x82`\x07\x0a\xa2\
+\x00\x00\x00\x12\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x01\x82`\x07!\xf4\
+"
+
+def qInitResources():
+ QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+def qCleanupResources():
+ QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+qInitResources()
diff --git a/examples/charts/pointselectionandmarkers/utilities.py b/examples/charts/pointselectionandmarkers/utilities.py
new file mode 100644
index 000000000..b27a2542b
--- /dev/null
+++ b/examples/charts/pointselectionandmarkers/utilities.py
@@ -0,0 +1,77 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtGui import QImage, QPainter, QColor
+from PySide6.QtCore import Qt
+
+import rc_markers # noqa: F401
+
+
+def rectangle(point_type, image_size):
+ image = QImage(image_size, image_size, QImage.Format_RGB32)
+ painter = QPainter()
+ painter.begin(image)
+ painter.setRenderHint(QPainter.Antialiasing)
+ painter.fillRect(0, 0, image_size, image_size, point_type[2])
+ painter.end()
+ return image
+
+
+def triangle(point_type, image_size):
+ return QImage(point_type[3]).scaled(image_size, image_size)
+
+
+def circle(point_type, image_size):
+ image = QImage(image_size, image_size, QImage.Format_ARGB32)
+ image.fill(QColor(0, 0, 0, 0))
+ painter = QPainter()
+ painter.begin(image)
+ painter.setRenderHint(QPainter.Antialiasing)
+ painter.setBrush(point_type[2])
+ pen = painter.pen()
+ pen.setWidth(0)
+ painter.setPen(pen)
+ painter.drawEllipse(0, 0, image_size * 0.9, image_size * 0.9)
+ painter.end()
+ return image
+
+
+_point_types = [("RedRectangle", rectangle, Qt.red),
+ ("GreenTriangle", triangle, Qt.green, ":/images/green_triangle.png"),
+ ("OrangeCircle", circle, QColor(255, 127, 80))]
+_selected_point_types = [("BlueTriangle", triangle, Qt.blue, ":/images/blue_triangle.png"),
+ ("YellowRectangle", rectangle, Qt.yellow),
+ ("LavenderCircle", circle, QColor(147, 112, 219))]
+_line_colors = [("Blue", QColor(65, 105, 225)), ("Black", Qt.black), ("Mint", QColor(70, 203, 155))]
+
+
+def point_type(index):
+ return _point_types[index]
+
+
+def selected_point_type(index):
+ return _selected_point_types[index]
+
+
+def line_color(index):
+ return _line_colors[index]
+
+
+def default_light_marker(image_size):
+ return rectangle(_point_types[0], image_size)
+
+
+def default_selected_light_marker(image_size):
+ return triangle(_selected_point_types[0], image_size)
+
+
+def get_point_representation(point_type, image_size):
+ return point_type[1](point_type, image_size)
+
+
+def get_selected_point_representation(point_type, image_size):
+ return point_type[1](point_type, image_size)
+
+
+def make_line_color(line_color):
+ return line_color[1]
diff --git a/examples/charts/qmlpolarchart/View1.qml b/examples/charts/qmlpolarchart/View1.qml
new file mode 100644
index 000000000..d05f7e2a2
--- /dev/null
+++ b/examples/charts/qmlpolarchart/View1.qml
@@ -0,0 +1,52 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtCharts
+
+Item {
+ anchors.fill: parent
+ //![1]
+ PolarChartView {
+ title: "Two Series, Common Axes"
+ anchors.fill: parent
+ legend.visible: false
+ antialiasing: true
+
+ ValueAxis {
+ id: axisAngular
+ min: 0
+ max: 20
+ tickCount: 9
+ }
+
+ ValueAxis {
+ id: axisRadial
+ min: -0.5
+ max: 1.5
+ }
+
+ SplineSeries {
+ id: series1
+ axisAngular: axisAngular
+ axisRadial: axisRadial
+ pointsVisible: true
+ }
+
+ ScatterSeries {
+ id: series2
+ axisAngular: axisAngular
+ axisRadial: axisRadial
+ markerSize: 10
+ }
+ }
+
+ // Add data dynamically to the series
+ Component.onCompleted: {
+ for (var i = 0; i <= 20; i++) {
+ series1.append(i, Math.random());
+ series2.append(i, Math.random());
+ }
+ }
+ //![1]
+}
diff --git a/examples/charts/qmlpolarchart/View2.qml b/examples/charts/qmlpolarchart/View2.qml
new file mode 100644
index 000000000..1db760396
--- /dev/null
+++ b/examples/charts/qmlpolarchart/View2.qml
@@ -0,0 +1,73 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtCharts
+
+Item {
+ anchors.fill: parent
+
+ //![1]
+ PolarChartView {
+ title: "Historical Area Series"
+ anchors.fill: parent
+ legend.visible: false
+ antialiasing: true
+
+ DateTimeAxis {
+ id: axis1
+ format: "yyyy MMM"
+ tickCount: 13
+ }
+ ValueAxis {
+ id: axis2
+ }
+ LineSeries {
+ id: lowerLine
+ axisAngular: axis1
+ axisRadial: axis2
+
+ // Please note that month in JavaScript months are zero based, so 2 means March
+ XYPoint { x: toMsecsSinceEpoch(new Date(1950, 0, 1)); y: 15 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1962, 4, 1)); y: 35 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1970, 0, 1)); y: 50 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1978, 2, 1)); y: 75 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1987, 11, 1)); y: 102 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1992, 1, 1)); y: 132 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1998, 7, 1)); y: 100 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(2002, 4, 1)); y: 120 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(2012, 8, 1)); y: 140 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(2013, 5, 1)); y: 150 }
+ }
+ LineSeries {
+ id: upperLine
+ axisAngular: axis1
+ axisRadial: axis2
+
+ // Please note that month in JavaScript months are zero based, so 2 means March
+ XYPoint { x: toMsecsSinceEpoch(new Date(1950, 0, 1)); y: 30 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1962, 4, 1)); y: 55 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1970, 0, 1)); y: 80 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1978, 2, 1)); y: 105 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1987, 11, 1)); y: 125 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1992, 1, 1)); y: 160 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(1998, 7, 1)); y: 140 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(2002, 4, 1)); y: 140 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(2012, 8, 1)); y: 170 }
+ XYPoint { x: toMsecsSinceEpoch(new Date(2013, 5, 1)); y: 200 }
+ }
+ AreaSeries {
+ axisAngular: axis1
+ axisRadial: axis2
+ lowerSeries: lowerLine
+ upperSeries: upperLine
+ }
+ }
+ // DateTimeAxis is based on QDateTimes so we must convert our JavaScript dates to
+ // milliseconds since epoch to make them match the DateTimeAxis values
+ function toMsecsSinceEpoch(date) {
+ var msecs = date.getTime();
+ return msecs;
+ }
+ //![1]
+}
diff --git a/examples/charts/qmlpolarchart/View3.qml b/examples/charts/qmlpolarchart/View3.qml
new file mode 100644
index 000000000..f684d55e0
--- /dev/null
+++ b/examples/charts/qmlpolarchart/View3.qml
@@ -0,0 +1,60 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtCharts
+
+Item {
+ anchors.fill: parent
+
+ //![1]
+ PolarChartView {
+ title: "Numerical Data for Dummies"
+ anchors.fill: parent
+ legend.visible: false
+ antialiasing: true
+
+ LineSeries {
+ axisRadial: CategoryAxis {
+ min: 0
+ max: 30
+ CategoryRange {
+ label: "critical"
+ endValue: 2
+ }
+ CategoryRange {
+ label: "low"
+ endValue: 7
+ }
+ CategoryRange {
+ label: "normal"
+ endValue: 12
+ }
+ CategoryRange {
+ label: "high"
+ endValue: 18
+ }
+ CategoryRange {
+ label: "extremely high"
+ endValue: 30
+ }
+ }
+
+ axisAngular: ValueAxis {
+ tickCount: 13
+ }
+
+ XYPoint { x: 0; y: 4.3 }
+ XYPoint { x: 1; y: 4.1 }
+ XYPoint { x: 2; y: 4.7 }
+ XYPoint { x: 3; y: 3.9 }
+ XYPoint { x: 4; y: 5.2 }
+ XYPoint { x: 5; y: 5.3 }
+ XYPoint { x: 6; y: 6.1 }
+ XYPoint { x: 7; y: 7.7 }
+ XYPoint { x: 8; y: 12.9 }
+ XYPoint { x: 9; y: 19.2 }
+ }
+ }
+ //![1]
+}
diff --git a/examples/charts/qmlpolarchart/doc/qmlpolarchart.png b/examples/charts/qmlpolarchart/doc/qmlpolarchart.png
new file mode 100644
index 000000000..7fbb63d82
--- /dev/null
+++ b/examples/charts/qmlpolarchart/doc/qmlpolarchart.png
Binary files differ
diff --git a/examples/charts/qmlpolarchart/doc/qmlpolarchart.rst b/examples/charts/qmlpolarchart/doc/qmlpolarchart.rst
new file mode 100644
index 000000000..30b7b919f
--- /dev/null
+++ b/examples/charts/qmlpolarchart/doc/qmlpolarchart.rst
@@ -0,0 +1,8 @@
+QML Polar Chart Example
+=======================
+
+This is a demonstration on how to use a polar chart in your QML application.
+
+.. image:: qmlpolarchart.png
+ :width: 400
+ :alt: QML Polar Chart Screenshot
diff --git a/examples/charts/qmlpolarchart/main.qml b/examples/charts/qmlpolarchart/main.qml
new file mode 100644
index 000000000..6ced27ee2
--- /dev/null
+++ b/examples/charts/qmlpolarchart/main.qml
@@ -0,0 +1,63 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ width: 800
+ height: 600
+ property bool sourceLoaded: false
+
+ ListView {
+ id: root
+ focus: true
+ anchors.fill: parent
+ snapMode: ListView.SnapOneItem
+ highlightRangeMode: ListView.StrictlyEnforceRange
+ highlightMoveDuration: 250
+ orientation: ListView.Horizontal
+ boundsBehavior: Flickable.StopAtBounds
+
+ onCurrentIndexChanged: {
+ if (infoText.opacity > 0.0) {
+ if (sourceLoaded)
+ infoText.opacity = 0.0;
+ else if (currentIndex != 0)
+ currentIndex = 0;
+ }
+ }
+
+ model: ListModel {
+ ListElement {component: "View1.qml"}
+ ListElement {component: "View2.qml"}
+ ListElement {component: "View3.qml"}
+ }
+
+ delegate: Loader {
+ width: root.width
+ height: root.height
+
+ source: component
+ asynchronous: true
+
+ onLoaded: sourceLoaded = true
+ }
+ }
+
+ Rectangle {
+ id: infoText
+ anchors.centerIn: parent
+ width: parent.width
+ height: 40
+ color: "black"
+ Text {
+ color: "white"
+ anchors.centerIn: parent
+ text: "You can navigate between views using swipe or arrow keys"
+ }
+
+ Behavior on opacity {
+ NumberAnimation { duration: 400 }
+ }
+ }
+}
diff --git a/examples/charts/qmlpolarchart/qmlpolarchart.py b/examples/charts/qmlpolarchart/qmlpolarchart.py
new file mode 100644
index 000000000..6391fc305
--- /dev/null
+++ b/examples/charts/qmlpolarchart/qmlpolarchart.py
@@ -0,0 +1,28 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the QML Polar Chart Example from Qt v5.x"""
+
+import os
+from pathlib import Path
+import sys
+
+from PySide6.QtQuick import QQuickView
+from PySide6.QtCore import QUrl
+from PySide6.QtWidgets import QApplication
+
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+ viewer = QQuickView()
+
+ src_dir = Path(__file__).resolve().parent
+ viewer.engine().addImportPath(os.fspath(src_dir))
+ viewer.engine().quit.connect(viewer.close)
+
+ viewer.setTitle = "QML Polar Chart"
+ viewer.setSource(QUrl.fromLocalFile(src_dir / 'main.qml'))
+ viewer.setResizeMode(QQuickView.SizeRootObjectToView)
+ viewer.show()
+
+ sys.exit(app.exec())
diff --git a/examples/charts/qmlpolarchart/qmlpolarchart.pyproject b/examples/charts/qmlpolarchart/qmlpolarchart.pyproject
new file mode 100644
index 000000000..6c18b1f43
--- /dev/null
+++ b/examples/charts/qmlpolarchart/qmlpolarchart.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["View1.qml", "View1.qml", "View2.qml", "View3.qml", "main.qml", "qmlpolarchart.py"]
+}
diff --git a/examples/charts/temperaturerecords/doc/temperaturerecords.png b/examples/charts/temperaturerecords/doc/temperaturerecords.png
new file mode 100644
index 000000000..8d486c552
--- /dev/null
+++ b/examples/charts/temperaturerecords/doc/temperaturerecords.png
Binary files differ
diff --git a/examples/charts/temperaturerecords/doc/temperaturerecords.rst b/examples/charts/temperaturerecords/doc/temperaturerecords.rst
new file mode 100644
index 000000000..3b13817fb
--- /dev/null
+++ b/examples/charts/temperaturerecords/doc/temperaturerecords.rst
@@ -0,0 +1,10 @@
+Temperature Records Example
+===========================
+
+The example shows how to create a bar chart with negative bars.
+
+For our example we use temperature data.
+
+.. image:: temperaturerecords.png
+ :width: 400
+ :alt: Temperature Records Screenshot
diff --git a/examples/charts/temperaturerecords/temperaturerecords.py b/examples/charts/temperaturerecords/temperaturerecords.py
new file mode 100644
index 000000000..358f3818e
--- /dev/null
+++ b/examples/charts/temperaturerecords/temperaturerecords.py
@@ -0,0 +1,60 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the Temperature Records example from Qt v5.x"""
+
+import sys
+from PySide6.QtCore import Qt
+from PySide6.QtGui import QPainter
+from PySide6.QtWidgets import QMainWindow, QApplication
+from PySide6.QtCharts import (QBarCategoryAxis, QBarSet, QChart, QChartView,
+ QStackedBarSeries, QValueAxis)
+
+
+class MainWindow(QMainWindow):
+ def __init__(self):
+ super().__init__()
+ low = QBarSet("Min")
+ high = QBarSet("Max")
+ low.append([-52, -50, -45.3, -37.0, -25.6, -8.0,
+ -6.0, -11.8, -19.7, -32.8, -43.0, -48.0])
+ high.append([11.9, 12.8, 18.5, 26.5, 32.0, 34.8,
+ 38.2, 34.8, 29.8, 20.4, 15.1, 11.8])
+
+ series = QStackedBarSeries()
+ series.append(low)
+ series.append(high)
+
+ chart = QChart()
+ chart.addSeries(series)
+ chart.setTitle("Temperature records in celcius")
+ chart.setAnimationOptions(QChart.SeriesAnimations)
+
+ categories = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
+ "Aug", "Sep", "Oct", "Nov", "Dec"]
+ axis_x = QBarCategoryAxis()
+ axis_x.append(categories)
+ axis_x.setTitleText("Month")
+ chart.addAxis(axis_x, Qt.AlignBottom)
+ axis_y = QValueAxis()
+ axis_y.setRange(-52, 52)
+ axis_y.setTitleText("Temperature [&deg;C]")
+ chart.addAxis(axis_y, Qt.AlignLeft)
+ series.attachAxis(axis_x)
+ series.attachAxis(axis_y)
+
+ chart.legend().setVisible(True)
+ chart.legend().setAlignment(Qt.AlignBottom)
+
+ chart_view = QChartView(chart)
+ chart_view.setRenderHint(QPainter.Antialiasing)
+
+ self.setCentralWidget(chart_view)
+
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+ w = MainWindow()
+ w.resize(600, 300)
+ w.show()
+ sys.exit(app.exec())
diff --git a/examples/charts/temperaturerecords/temperaturerecords.pyproject b/examples/charts/temperaturerecords/temperaturerecords.pyproject
new file mode 100644
index 000000000..8db39e340
--- /dev/null
+++ b/examples/charts/temperaturerecords/temperaturerecords.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["temperaturerecords.py"]
+}