diff options
author | Keith Kyzivat <keith.kyzivat@qt.io> | 2022-11-10 14:27:53 -0500 |
---|---|---|
committer | Keith Kyzivat <keith.kyzivat@qt.io> | 2023-01-19 15:45:48 -0500 |
commit | 8111875a7fe11b856bc2c6960d7b196607bc1f0c (patch) | |
tree | 48bfec417d93a8cdc114bc83638d32a966770a9b /examples | |
parent | 50d3f6cd3ab69d9f5dadb8cc308b3aeaf8c27938 (diff) |
PySide6-examples: Charts selected point configuration example
Add an example that shows how to customize individual points on a chart,
such as changing the color or providing a a custom label.
Task-number: PYSIDE-841
Change-Id: I09b48dd4e77f03355d1bb1207d7666a9fb3801f0
Reviewed-by: Venugopal Shivashankar <Venugopal.Shivashankar@qt.io>
Diffstat (limited to 'examples')
-rw-r--r-- | examples/charts/pointconfiguration/chartwindow.py | 157 | ||||
-rw-r--r-- | examples/charts/pointconfiguration/doc/pointconfiguration.png | bin | 0 -> 34991 bytes | |||
-rw-r--r-- | examples/charts/pointconfiguration/doc/pointconfiguration.rst | 148 | ||||
-rw-r--r-- | examples/charts/pointconfiguration/pointconfiguration.py | 17 | ||||
-rw-r--r-- | examples/charts/pointconfiguration/pointconfiguration.pyproject | 3 |
5 files changed, 325 insertions, 0 deletions
diff --git a/examples/charts/pointconfiguration/chartwindow.py b/examples/charts/pointconfiguration/chartwindow.py new file mode 100644 index 000000000..93acca506 --- /dev/null +++ b/examples/charts/pointconfiguration/chartwindow.py @@ -0,0 +1,157 @@ +# 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 QObject, 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 + + +PointConfig = QXYSeries.PointConfiguration + + +class ChartWindow(QMainWindow): + def __init__(self, parent:QObject=None ): + super().__init__(parent) + + tr=self.tr + self.setWindowTitle(tr("Chart")) + self._series = QLineSeries(self) + self._series.setName(tr("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(tr("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(tr("Color: ")) + self._color_combobox = QComboBox() + color_strings = ["red", "orange", "yellow", "green", "blue", "indigo", "violet", "black"] + tr_color_strings = [tr("red"), tr("orange"), tr("yellow"), tr("green"), tr("blue"), + tr("indigo"), tr("violet"), tr("black")] + for i, color_str in enumerate(color_strings): + self._color_combobox.addItem(QIcon(), tr_color_strings[i], QColor(color_str)) + + size_label = QLabel(tr("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(tr("Label Visibility: ")) + self._label_visibility_checkbox = QCheckBox() + + custom_label_label = QLabel(tr("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) + self._label_visibility_checkbox.clicked.connect(self._set_label_visibility) + self._custom_label_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._series.clicked.emit(self._series.at(4)) + + @Slot(QPointF) + def _select_point(self, point: QPointF): + try: + index = self._series.points().index(point.toPoint()) + self._series.deselectAllPoints() + self._series.selectPoint(index) + self._selectedPointIndex = index + self._selectedPointConfig = self._series.pointConfiguration(index) + selected_point = self._series.at(index) + self._selected_point_index_lineedit.setText("(" + str(selected_point.x()) + ", " + + str(selected_point.y()) + ")") + config = self._series.pointConfiguration(index) + + try: + color = config[PointConfig.Color] + except KeyError: + color = self._series.color() + if self._color_combobox.findData(color) < 0: + self._color_combobox.addItem(color.name(), color) + self._color_combobox.setCurrentIndex(self._color_combobox.findData(color)) + + try: + size = config[PointConfig.Size] + except KeyError: + size = self._series.markerSize() + if self._size_combobox.findData(size) < 0: + self._size_combobox.addItem(str(size), size) + self._size_combobox.setCurrentIndex(self._size_combobox.findData(size)) + + try: + labelVisibility = config[PointConfig.LabelVisibility] + except KeyError: + labelVisibility = self._series.pointLabelsVisible() + self._label_visibility_checkbox.setChecked(labelVisibility) + + try: + customLabel = config[PointConfig.LabelFormat] + except KeyError: + customLabel = "" + self._custom_label_lineedit.setText(customLabel) + except ValueError: + # Do nothing if the place that was clicked on wasn't a point. + pass + + @Slot(int) + def _set_color(self, index: int): + self._selectedPointConfig[PointConfig.Color] = self._color_combobox.currentData() + self._series.setPointConfiguration(self._selectedPointIndex, self._selectedPointConfig) + + @Slot(int) + def _set_size(self, index: int): + self._selectedPointConfig[PointConfig.Size] = self._size_combobox.currentData() + self._series.setPointConfiguration(self._selectedPointIndex, self._selectedPointConfig) + + @Slot(bool) + def _set_label_visibility(self, checked: bool): + self._selectedPointConfig[PointConfig.LabelVisibility] = checked + self._series.setPointConfiguration(self._selectedPointIndex, self._selectedPointConfig) + + @Slot() + def _set_custom_label(self): + self._selectedPointConfig[PointConfig.LabelFormat] = self._custom_label_lineedit.text() + self._series.setPointConfiguration(self._selectedPointIndex, self._selectedPointConfig) diff --git a/examples/charts/pointconfiguration/doc/pointconfiguration.png b/examples/charts/pointconfiguration/doc/pointconfiguration.png Binary files differnew file mode 100644 index 000000000..791698587 --- /dev/null +++ b/examples/charts/pointconfiguration/doc/pointconfiguration.png diff --git a/examples/charts/pointconfiguration/doc/pointconfiguration.rst b/examples/charts/pointconfiguration/doc/pointconfiguration.rst new file mode 100644 index 000000000..63cade471 --- /dev/null +++ b/examples/charts/pointconfiguration/doc/pointconfiguration.rst @@ -0,0 +1,148 @@ +.. 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:: ../../../../examples/charts/pointconfiguration/chartwindow.py + :linenos: + :lineno-start: 15 + :lines: 15-17 + +Create a line series +~~~~~~~~~~~~~~~~~~~~ + +Create a :py:`QLineSeries` containing the points to plot. Give it a name and make the points +visible. + +.. literalinclude:: ../../../../examples/charts/pointconfiguration/chartwindow.py + :linenos: + :lineno-start: 20 + :lines: 20-27 + +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:: ../../../../examples/charts/pointconfiguration/chartwindow.py + :linenos: + :lineno-start: 29 + :lines: 29-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:: ../../../../examples/charts/pointconfiguration/chartwindow.py + :linenos: + :lineno-start: 54 + :lines: 54 +.. literalinclude:: ../../../../examples/charts/pointconfiguration/chartwindow.py + :linenos: + :lineno-start: 95 + :lines: 95-137 + +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:: ../../../../examples/charts/pointconfiguration/chartwindow.py + :linenos: + :lineno-start: 55 + :lines: 55-58 +.. literalinclude:: ../../../../examples/charts/pointconfiguration/chartwindow.py + :linenos: + :lineno-start: 139 + :lines: 139-157 + +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:: ../../../../examples/charts/pointconfiguration/chartwindow.py + :linenos: + :lineno-start: 60 + :lines: 60-93 +.. literalinclude:: ../../../../examples/charts/pointconfiguration/chartwindow.py + :linenos: + :lineno-start: 159 + :lines: 159-163 + +In our entrypoint file `pointconfiguration.py`, instantiate the :py:`ChartWindow`, resize it, show +it, and start the event loop. + +.. literalinclude:: ../../../../examples/charts/pointconfiguration/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"] +} |