This example shows how to modify the configuration of individual points.
In this application you will learn how to:
要运行范例从 Qt Creator ,打开 Welcome 模式,然后选择范例从 Examples 。更多信息,拜访 构建和运行范例 .
We start by creating a subclass of QMainWindow that will contain the chart and controls.
class ChartWindow : public QMainWindow { Q_OBJECT public: explicit ChartWindow(QWidget *parent = nullptr); ~ChartWindow() {}; private: QChart *m_chart = nullptr; QXYSeries *m_series = nullptr; QMetaObject::Connection m_selectInitialPointConnection; int m_selectedPointIndex = -1; PointConfigurations m_selectedPointConfig; QLineEdit *m_selectedPointIndexLineEdit = nullptr; QComboBox *m_colorCombobox = nullptr; QComboBox *m_sizeCombobox = nullptr; QCheckBox *m_labelVisibilityCheckbox = nullptr; QLineEdit *m_customLabelLineEdit = nullptr; };
And we provide the boilerplate for the constructor implementation:
ChartWindow::ChartWindow(QWidget *parent) : QMainWindow(parent) { }
Then we create a QLineSeries , giving it a name, making the points visible, and giving it some points to plot.
setWindowTitle(tr("Chart")); m_series = new QLineSeries(this); m_series->setName(tr("Customized series")); m_series->setPointsVisible(true); m_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)});
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.
QLabel *selectedPointIndexLabel = new QLabel(tr("Selected Point: ")); m_selectedPointIndexLineEdit = new QLineEdit(); m_selectedPointIndexLineEdit->setReadOnly(true); QLabel *colorLabel = new QLabel(tr("Color: ")); m_colorCombobox = new QComboBox(); 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 < colorStrings.size(); i++) m_colorCombobox->addItem(QIcon(), trColorStrings[i], QColor(colorStrings[i])); QLabel *sizeLabel = new QLabel(tr("Size: ")); m_sizeCombobox = new QComboBox(); for (auto size : { 2, 3, 4, 6, 8, 10, 12, 15 }) m_sizeCombobox->addItem(QIcon(), QString::number(size), size); QLabel *labelVisibilityLabel = new QLabel(tr("Label Visibility: ")); m_labelVisibilityCheckbox = new QCheckBox(); QLabel *customLabelLabel = new QLabel(tr("Custom Label: ")); m_customLabelLineEdit = new QLineEdit();
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, &QXYSeries::clicked, m_series, [&](const QPointF &point) { int index = m_series->points().indexOf(point.toPoint()); if (index != -1) { m_series->deselectAllPoints(); m_series->selectPoint(index); m_selectedPointIndex = index; m_selectedPointConfig = m_series->pointConfiguration(index); const QPointF selectedPoint(m_series->at(index)); m_selectedPointIndexLineEdit->setText("(" + QString::number(selectedPoint.x()) + ", " + QString::number(selectedPoint.y()) + ")"); PointConfigurations config = m_series->pointConfiguration(index); QVariant colorVar = config[QXYSeries::PointConfiguration::Color]; QColor color = colorVar.isValid() ? colorVar.value<QColor>() : m_series->color(); if (m_colorCombobox->findData(color) < 0) m_colorCombobox->addItem(color.name(), color); m_colorCombobox->setCurrentIndex(m_colorCombobox->findData(color)); QVariant sizeVar = config[QXYSeries::PointConfiguration::Size]; qreal size = sizeVar.isValid() ? sizeVar.toReal() : m_series->markerSize(); if (m_sizeCombobox->findData(size) < 0) m_sizeCombobox->addItem(QString::number(size), size); m_sizeCombobox->setCurrentIndex(m_sizeCombobox->findData(size)); QVariant labelVisibilityVar = config[QXYSeries::PointConfiguration::LabelVisibility]; bool labelVisibility = labelVisibilityVar.isValid() ? labelVisibilityVar.toBool() : m_series->pointLabelsVisible(); m_labelVisibilityCheckbox->setChecked(labelVisibility); QVariant customLabelVar = config[QXYSeries::PointConfiguration::LabelFormat]; QString customLabel = customLabelVar.isValid() ? customLabelVar.toString() : ""; m_customLabelLineEdit->setText(customLabel); } });
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, &QComboBox::activated, m_series, [&](const int index) { m_selectedPointConfig[QXYSeries::PointConfiguration::Color] = m_colorCombobox->currentData(); m_series->setPointConfiguration(m_selectedPointIndex, m_selectedPointConfig); }); QObject::connect(m_sizeCombobox, &QComboBox::activated, m_series, [&](const int index) { m_selectedPointConfig[QXYSeries::PointConfiguration::Size] = m_sizeCombobox->currentData(); m_series->setPointConfiguration(m_selectedPointIndex, m_selectedPointConfig); }); QObject::connect(m_labelVisibilityCheckbox, &QAbstractButton::clicked, m_series, [&](const bool checked) { m_selectedPointConfig[QXYSeries::PointConfiguration::LabelVisibility] = checked; m_series->setPointConfiguration(m_selectedPointIndex, m_selectedPointConfig); }); QObject::connect(m_customLabelLineEdit, &QLineEdit::editingFinished, m_series, [&]() { m_selectedPointConfig[QXYSeries::PointConfiguration::LabelFormat] = m_customLabelLineEdit->text(); m_series->setPointConfiguration(m_selectedPointIndex, m_selectedPointConfig); });
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.
m_chart = new QChart(); m_chart->addSeries(m_series); m_chart->createDefaultAxes(); m_selectInitialPointConnection = QObject::connect(m_chart, &QChart::geometryChanged, m_chart, [&]() { m_series->selectPoint(4); m_series->clicked(m_series->at(m_series->selectedPoints()[0])); disconnect(m_selectInitialPointConnection); }); QChartView *chartView = new QChartView(m_chart); chartView->setRenderHint(QPainter::Antialiasing); QWidget *controlWidget = new QWidget(this); QGridLayout *controlLayout = new QGridLayout(controlWidget); controlLayout->setColumnStretch(1, 1); controlLayout->addWidget(selectedPointIndexLabel, 0, 0); controlLayout->addWidget(m_selectedPointIndexLineEdit, 0, 1); controlLayout->addWidget(colorLabel, 1, 0); controlLayout->addWidget(m_colorCombobox, 1, 1); controlLayout->addWidget(sizeLabel, 2, 0); controlLayout->addWidget(m_sizeCombobox, 2, 1); controlLayout->addWidget(labelVisibilityLabel, 3, 0); controlLayout->addWidget(m_labelVisibilityCheckbox, 3, 1, 1, 2); controlLayout->addWidget(customLabelLabel, 4, 0); controlLayout->addWidget(m_customLabelLineEdit, 4, 1); QWidget *mainWidget = new QWidget(this); QHBoxLayout *mainLayout = new QHBoxLayout(mainWidget); mainLayout->addWidget(chartView); mainLayout->setStretch(0, 1); mainLayout->addWidget(controlWidget); setCentralWidget(mainWidget);
在
main.cpp
we simply instantiate the
ChartWindow
, resize it, show it, and start the event loop.
int main(int argc, char *argv[]) { QApplication a(argc, argv); ChartWindow mainWindow; mainWindow.resize(640, 480); mainWindow.show(); return a.exec(); }
Now we have a fully functioning application that demonstrates how to customize individual chart points.