Selected Point Configuration▲
This is part of the Charts with Widgets Gallery example.
Features Demonstrated▲
Here you will learn how to:
-
Provide click-selection of points in a series.
-
Override the individual configuration of specific points, configuring:
-
Color
-
Size
-
Visibility of the label
-
Text format of the label
-
Running the Example▲
To run the example from Qt Creator, open the Welcome mode and select the example from Examples. For more information, visit Building and Running an Example.
Subclass QMainWindow▲
We start by creating a subclass of QMainWindow that will contain the chart and controls. And we provide the boilerplate for the constructor implementation:
PointConfigurationWidget::
PointConfigurationWidget(QWidget *
parent)
:
ContentWidget(parent)
{
Create a Line Series▲
Then we create a QLineSeries, giving it a name, making the points visible, and giving it some points to plot.
m_series =
new
QLineSeries;
m_series-&
gt;setPointsVisible(true
);
m_series-&
gt;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
)}
);
Create the Point Configuration Controls▲
Now we create some controls to configure the color, size, label visibility, and the label itself. We create an associated label for each control so the user knows what the control does.
For the color and size, we use a QComboBox, populating it with a variety of color and size choices.
Next we create the final two controls. A Checkbox controls the visibility of the selected point. The other control is a QLineEdit allowing the user to provide a custom label for the point.
Note that we do not set initial values for any of the controls, as a point will always be selected showing its current settings.
auto
selectedPointIndexLabel =
new
QLabel(tr("Selected Point: "
), this
);
m_selectedPointIndexLineEdit =
new
QLineEdit(this
);
m_selectedPointIndexLineEdit-&
gt;setReadOnly(true
);
auto
colorLabel =
new
QLabel(tr("Color: "
), this
);
m_colorCombobox =
new
QComboBox(this
);
QStringList colorStrings =
{
"red"
, "orange"
, "yellow"
, "green"
, "blue"
,
"indigo"
, "violet"
, "black"
}
;
QStringList trColorStrings =
{
tr("red"
), tr("orange"
), tr("yellow"
),
tr("green"
), tr("blue"
), tr("indigo"
),
tr("violet"
), tr("black"
)}
;
for
(int
i =
0
; i &
lt; colorStrings.size(); i++
)
m_colorCombobox-&
gt;addItem(QIcon(), trColorStrings[i], QColor(colorStrings[i]));
auto
sizeLabel =
new
QLabel(tr("Size: "
), this
);
m_sizeCombobox =
new
QComboBox(this
);
for
(auto
size : {
2
, 3
, 4
, 6
, 8
, 10
, 12
, 15
}
)
m_sizeCombobox-&
gt;addItem(QIcon(), QString::
number(size), size);
auto
labelVisibilityLabel =
new
QLabel(tr("Label Visibility: "
), this
);
m_labelVisibilityCheckbox =
new
QCheckBox(this
);
auto
customLabelLabel =
new
QLabel(tr("Custom Label: "
), this
);
m_customLabelLineEdit =
new
QLineEdit(this
);
Populate the Controls upon Selecting a Point▲
Now that we have the controls, we need to provide the logic that sets the current control values for the selected 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.
Upon clicking on the lineseries, we look up the point clicked on, remove the prior point selection, and then select the point that was clicked on. This visually indicates the selected point on the chart - making the point larger to indicate its selection. The index of the current selected point and its PointConfigurations are saved to a member variable for later use.
The PointConfigurations are queried and matching values in the comboboxes are looked up. Then the current indices of the comboboxes are set accordingly. Similarly for the checkbox and line edit, the values are looked up from the PointConfigurations, and the controls are set to match them.
QObject::
connect(m_series, &
amp;QXYSeries::
clicked, m_series, [&
amp;](const
QPointF &
amp;point) {
int
index =
m_series-&
gt;points().indexOf(point.toPoint());
if
(index !=
-
1
) {
m_series-&
gt;deselectAllPoints();
m_series-&
gt;selectPoint(index);
m_selectedPointIndex =
index;
m_selectedPointConfig =
m_series-&
gt;pointConfiguration(index);
const
QPointF selectedPoint(m_series-&
gt;at(index));
m_selectedPointIndexLineEdit-&
gt;setText("("
+
QString::
number(selectedPoint.x()) +
", "
+
QString::
number(selectedPoint.y()) +
")"
);
PointConfigurations config =
m_series-&
gt;pointConfiguration(index);
QVariant colorVar =
config[QXYSeries::PointConfiguration::
Color];
QColor color =
colorVar.isValid() ? colorVar.value&
lt;QColor&
gt;() : m_series-&
gt;color();
if
(m_colorCombobox-&
gt;findData(color) &
lt; 0
)
m_colorCombobox-&
gt;addItem(color.name(), color);
m_colorCombobox-&
gt;setCurrentIndex(m_colorCombobox-&
gt;findData(color));
QVariant sizeVar =
config[QXYSeries::PointConfiguration::
Size];
qreal size =
sizeVar.isValid() ? sizeVar.toReal() : m_series-&
gt;markerSize();
if
(m_sizeCombobox-&
gt;findData(size) &
lt; 0
)
m_sizeCombobox-&
gt;addItem(QString::
number(size), size);
m_sizeCombobox-&
gt;setCurrentIndex(m_sizeCombobox-&
gt;findData(size));
QVariant labelVisibilityVar =
config[QXYSeries::PointConfiguration::
LabelVisibility];
bool
labelVisibility =
labelVisibilityVar.isValid() ? labelVisibilityVar.toBool() :
m_series-&
gt;pointLabelsVisible();
m_labelVisibilityCheckbox-&
gt;setChecked(labelVisibility);
QVariant customLabelVar =
config[QXYSeries::PointConfiguration::
LabelFormat];
QString customLabel =
customLabelVar.isValid() ? customLabelVar.toString() : ""
;
m_customLabelLineEdit-&
gt;setText(customLabel);
}
}
);
Provide the Logic to Configure the Selected Point▲
Now that the controls are populated with the current configuration, we need to make them do something. We connect up their signals to logic that will do the work of configuring the selected point with the setting chosen. It is a simple matter of setting the QXYSeries::PointConfiguration value associated with the control to the m_selectedPointConfig PointConfigurations member variable, and calling QXYSeries::setPointConfiguration.
QObject::
connect(m_colorCombobox, &
amp;QComboBox::
activated, m_series, [&
amp;](const
int
) {
m_selectedPointConfig[QXYSeries::PointConfiguration::
Color] =
m_colorCombobox-&
gt;currentData();
m_series-&
gt;setPointConfiguration(m_selectedPointIndex, m_selectedPointConfig);
}
);
QObject::
connect(m_sizeCombobox, &
amp;QComboBox::
activated, m_series, [&
amp;](const
int
) {
m_selectedPointConfig[QXYSeries::PointConfiguration::
Size] =
m_sizeCombobox-&
gt;currentData();
m_series-&
gt;setPointConfiguration(m_selectedPointIndex, m_selectedPointConfig);
}
);
QObject::
connect(m_labelVisibilityCheckbox, &
amp;QAbstractButton::
clicked, m_series, [&
amp;](const
bool
checked) {
m_selectedPointConfig[QXYSeries::PointConfiguration::
LabelVisibility] =
checked;
m_series-&
gt;setPointConfiguration(m_selectedPointIndex, m_selectedPointConfig);
}
);
QObject::
connect(m_customLabelLineEdit, &
amp;QLineEdit::
editingFinished, m_series, [&
amp;]() {
m_selectedPointConfig[QXYSeries::PointConfiguration::
LabelFormat] =
m_customLabelLineEdit-&
gt;text();
m_series-&
gt;setPointConfiguration(m_selectedPointIndex, m_selectedPointConfig);
}
);
Create the Chart and Lay out the Controls▲
Finally we create the chart and its view, add the series to the chart, and create the layout of the window. As part of this, we connect to the geometryChanged signal to catch a signal when the chart is first painted. This is so that we can get correct values for the initially selected point. If we do this earlier, the point values are incorrect. This connection is disconnected after the first time that it is fired.
auto
chart =
new
QChart;
chart-&
gt;addSeries(m_series);
chart-&
gt;createDefaultAxes();
chart-&
gt;setTitle("Select points with mouse click"
);
chart-&
gt;layout()-&
gt;setContentsMargins(0
, 0
, 0
, 0
);
chart-&
gt;legend()-&
gt;setVisible(false
);
m_selectInitialPointConnection =
QObject::
connect(chart, &
amp;QChart::
geometryChanged, chart, [&
amp;]() {
m_series-&
gt;selectPoint(4
);
m_series-&
gt;clicked(m_series-&
gt;at(m_series-&
gt;selectedPoints()[0
]));
disconnect(m_selectInitialPointConnection);
}
);
auto
chartView =
new
QChartView(chart, this
);
chartView-&
gt;setRenderHint(QPainter::
Antialiasing);
auto
controlWidget =
new
QWidget(this
);
auto
controlLayout =
new
QGridLayout(controlWidget);
controlLayout-&
gt;setColumnStretch(1
, 1
);
controlLayout-&
gt;addWidget(selectedPointIndexLabel, 0
, 0
);
controlLayout-&
gt;addWidget(m_selectedPointIndexLineEdit, 0
, 1
);
controlLayout-&
gt;addWidget(colorLabel, 1
, 0
);
controlLayout-&
gt;addWidget(m_colorCombobox, 1
, 1
);
controlLayout-&
gt;addWidget(sizeLabel, 2
, 0
);
controlLayout-&
gt;addWidget(m_sizeCombobox, 2
, 1
);
controlLayout-&
gt;addWidget(labelVisibilityLabel, 3
, 0
);
controlLayout-&
gt;addWidget(m_labelVisibilityCheckbox, 3
, 1
, 1
, 2
);
controlLayout-&
gt;addWidget(customLabelLabel, 4
, 0
);
controlLayout-&
gt;addWidget(m_customLabelLineEdit, 4
, 1
);
auto
mainLayout =
new
QHBoxLayout(this
);
mainLayout-&
gt;addWidget(chartView);
mainLayout-&
gt;setStretch(0
, 1
);
mainLayout-&
gt;addWidget(controlWidget);
Now we have a fully functioning application that demonstrates how to customize individual chart points.