//Creating Charts
//不同类型的图表分别生成并添加到布局中
//如,折线图创建如下。 其他图表类型的创建与此类似。
//首先创建一个图表。
QChart *chart = new QChart();
chart->setTitle("Line chart");
//生成一组通用的随机数据并将其放置在列表中。
//此列表用于每个图表类型以将数据添加到图表系列。
//对于线系列,创建 QLineSeries 实例并将其添加到图表中。
QString name("Series ");
int nameIndex = 0;
for(const DataList &list : m_dataTable)
{
QLineSeries *series = new QLineSeries(chart);
for(const Data &data : list)
series->append(data.first);
series->setName(name + QString::number(nameIndex));
nameIndex++;
chart->addSeries(series);
}
//为线系列创建默认轴。
//我们还根据用于系列的数据范围指定轴的范围。
chart->createDefaultAxes();
chart->axes(Qt::Horizontal).first()->setRange(0,m_valueMax);
chart->axes(Qt::Vertical).first()->setRange(0,m_valueCount);
//我们还想在标签和 y 轴之间添加更多空间。
//为此,我们指定了一种向标签添加空格字符的标签格式。
//Add space to label to add space between labels and axis
QValueAxis *axisY = qobject_cast<QValueAxis*>(chart->axes(Qt::Vertical).first());
Q_ASSERT(axisY);
axisY->setLabelFormat("%.1f ");
//最后将折线图添加到网格布局中。
chartView = new QChartView(createLineChart());
m_ui->gridLayout->addWidget(chartView,1,2);
//Changing Theme
//用户可以选择要在示例中使用的内置主题。
//然后将此主题应用于布局中的所有图表
QChart::ChartTheme theme = static_cast<QChart::ChartTheme>(
m_ui->themeComboBox->itemData(m_ui->themeComboBox->currentIndex().toInt());
)
chartView->chart()->setTheme(theme);
//为了使结果看起来更和谐,应用程序的背景调色板被自定义以匹配所选主题。
//QPalette::Window 和 QPalette::WindowText 角色是根据所选主题设置的。
QPalette pal = window()->palette();
if(theme == QChart::ChartThemeLight)
{
pal.setColor(QPalette::Window,QRgb(0xf0f0f0));
pal.setColor(QPalette::WindowText,QRbg(0x404044));
}
//更改动画、图例和抗锯齿
//在此示例中,还可以查看更改动画、图例和抗锯齿如何影响图表的外观。
//根据用户的选择,在每个图表上设置使用的动画类型。
//图表中可能没有动画,或者有网格轴或系列的动画,或者两者都有。
QChart::AnimationOptions options(
m_ui->animatedComboBox->itemData(m_ui->animatedComboBox->currentIndex()).toInt();
);
if(!m_charts.isEmpty() &&m_charts.at(0)->chart()->animationOptions()!=options)
{
for(QCharView *chartView : charts)
{
chartView->chart()->setAnimationOptions(options);
}
}
//图表可以用图例显示。 图例可以与图表的不同侧对齐。
Qt:Alignment alignment(m_ui->legendComboBox->itemData(m_ui->legendComboBox->currentIndex()).toInt());
if(!alignment)
{
for(QChartView *chartView : charts)
{
chartView->chart()->legend()->hide();
}
}
else
{
for(QChartView *charView : charts)
{
chartView->chart()->legend()->setAlignment(alignment);
chartView->chart()->legend()->show();
}
}
//用户还可以查看更改抗锯齿选项如何更改图表的外观。
//抗锯齿根据用户的选择进行更新。
bool checked = m_ui->antialiasCheckBox->isChecked();
for(QChartView *chart : charts)
chart->setRenderHint(QPainter::Antialiasing,checked);
#include "themewidget.h"
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow window;
ThemeWidget *widget = new ThemeWidget();
window.setCentralWidget(widget);
window.resize(900, 600);
window.show();
return a.exec();
}
themewidget.h
#ifndef THEMEWIDGET_H
#define THEMEWIDGET_H
#include <QtWidgets/QWidget>
#include <QtCharts/QChartGlobal>
//QComboBox 提供了一种以占用最少屏幕空间的方式向用户呈现选项列表的方法。
//组合框是一个显示当前项目的选择小部件
//,可以弹出一个可选择项目的列表。
//组合框可以是可编辑的
//允许用户修改列表中的每个项目。
//组合框可以包含像素图和字符串;
//insertItem() 和 setItemText() 函数被适当地重载。
//对于可编辑的组合框,提供了函数 clearEditText() 以清除显示的字符串而不更改组合框的内容。
//如果组合框的当前项目发生变化,
//则会发出三个信号:
//currentIndexChanged()、currentTextChanged() 和 activate()。
//currentIndexChanged() 和 currentTextChanged() 总是被发出,
//无论更改是通过编程还是通过用户交互完成,
//而 activate() 仅在更改由用户交互引起时发出。
//当用户突出显示组合框弹出列表中的项目时,会发出 highlight() 信号
//所有三个信号都存在两种版本,
//一种带有 QString 参数,另一种带有 int 参数。
//如果用户选择或突出显示像素图,则仅发出 int 信号。
//每当可编辑组合框的文本发生更改时,就会发出 editTextChanged() 信号。
//当用户在可编辑的组合框中输入新字符串时,
//小部件可能会也可能不会插入它
//并且可以将它插入到多个位置
//默认策略是 InsertAtBottom,
//但您可以使用 setInsertPolicy() 更改此策略。
//可以使用 QValidator 将输入限制为可编辑的组合框;
//请参见 setValidator()。
//默认情况下,接受任何输入。
//例如,可以使用插入函数 insertItem() 和 insertItems() 填充组合框。
//可以使用 setItemText() 更改项目。
//可以使用 removeItem() 删除项目,可以使用 clear() 删除所有项目。
//当前项的文本由 currentText() 返回,编号项的文本由 text() 返回。
//当前项目可以使用 setCurrentIndex() 设置。
//组合框中的项目数由 count() 返回;
//可以使用 setMaxCount() 设置最大项目数。
//您可以允许使用 setEditable() 进行编辑。
//对于可编辑的组合框,您可以使用 setCompleter() 设置自动完成功能,
//并使用 setDuplicatesEnabled() 设置用户是否可以添加重复项。
//QComboBox 为其弹出列表使用模型/视图框架并存储其项目。
//默认情况下, QStandardItemModel 存储项目, QListView 子类显示弹出列表。
//您可以直接访问模型和视图(使用 model() 和 view())
//但 QComboBox 还提供设置和获取项目数据的功能(例如,setItemData() 和 itemText())。
//您还可以设置新模型和视图(使用 setModel() 和 setView())。
//对于组合框标签中的文本和图标,使用具有 Qt::DisplayRole 和 Qt::DecorationRole 的模型中的数据。请
//请注意,您不能更改 view() 的 SelectionMode,例如,通过使用setSelectionMode()。
QT_BEGIN_NAMESPACE
class QComboBox;
class QCheckBox;
class Ui_ThemeWidgetForm;
QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
class QChartView;
class QChart;
QT_END_NAMESPACE
//QList<T> 是 Qt 的通用容器类之一
//它将其项目存储在相邻的内存位置并提供基于索引的快速访问。
//QList<T> 和 QVarLengthArray<T> 提供类似的 API 和功能
//它们通常可以互换,但会产生性能后果。 以下是用例的概述:
//QList 应该是您的默认首选。
//QVarLengthArray 提供了一个在堆栈上保留空间的数组
//但如果需要,可以动态地增长到堆上。
//用于通常较小的短寿命容器是很好的。
//如果您需要一个真正的链表,它可以保证在列表中间插入恒定时间
//并使用迭代器到项目而不是索引,请使用 std::list。
//注意:QList 和 QVarLengthArray 都保证与 C 兼容的数组布局。
//注意:Qt 5 中的 QList 并不总是具有与 C 兼容的数组布局,
//我们经常建议使用 QVector 来代替,以获得更可预测的性能。
//在 Qt 6 中不再是这种情况,两个类现在共享一个实现并且可以互换使用。
//下面是一个存储整数的 QList 和一个存储 QString 值的 QList 的示例:
/*
QList<int> integerList;
QList<QString> stringList;
*/
//QList 将其项存储在连续内存数组中。
//通常,列表是以初始大小创建的。
//例如,以下代码构造了一个包含 200 个元素的 QList:
/*
QList<QString> list(200);
*/
//这些元素会自动使用默认构造的值进行初始化
//如果要使用不同的值初始化列表
//请将该值作为第二个参数传递给构造函数:
/*
QList<QString> list(200,"Pass");
*/
//您还可以随时调用 fill() 以使用值填充列表。
//QList 使用基于 0 的索引,就像 C++ 数组一样。
//要访问特定索引位置的项目,您可以使用 operator[]()。
//在非常量列表上,operator[]() 返回对可以在赋值左侧使用的项的引用:
/*
if(list[0] == "Liz")
list[0] = "Elizabeth";
*/
//对于只读访问,另一种语法是使用 at():
/*
for(qsizetype i = 0; i<list.size();++i)
{
if(list.at(i) == "Alfonso")
cout<<"Found Alfonso at position "<<i<<Qt::endl;
}
*/
//at() 可以比 operator[]() 更快,因为它永远不会导致发生深拷贝。
//访问存储在 QList 中的数据的另一种方法是调用 data()。
//该函数返回一个指向列表中第一项的指针。
//您可以使用指针直接访问和修改存储在列表中的元素。
//如果您需要将 QList 传递给接受普通 C++ 数组的函数,则该指针也很有用。
//如果要查找列表中特定值的所有出现,请使用 indexOf() 或 lastIndexOf()。
//前者从给定的索引位置开始向前搜索,后者向后搜索。
//如果找到匹配项,则两者都返回匹配项的索引; 否则,它们返回-1。
/*
qsizetype i = list.indexOf("Harumi");
if(i != -1)
cout<<"First occurrence of Harumi is at postion "<<i<<Qt::endl;
*/
//如果您只想检查列表是否包含特定值,请使用 contains()。
//如果您想找出特定值在列表中出现的次数,请使用 count()。
//QList 提供了这些基本函数来添加、移动和删除项目:
//insert()、replace()、remove()、prepend()、append()。
//除了 append()、prepend() 和 replace() 之外
//这些函数对于大型列表来说可能很慢(线性时间)
//因为它们需要将列表中的许多项移动到内存中的一个位置。
//如果您想要一个在中间提供快速插入/删除的容器类,请改用 std::list。
//与普通的 C++ 数组不同,QList 可以通过调用 resize() 随时调整大小。
//如果新大小大于旧大小,QList 可能需要重新分配整个列表。
//QList 试图通过预分配两倍于实际数据需求的内存来减少重新分配的次数。
//如果您正在逐步构建 QList 并预先知道它大约包含多少个元素
//您可以调用 Reserve(),要求 QList 预分配一定数量的内存。
//您还可以调用 capacity() 来找出 QList 实际分配了多少内存。
//请注意,由于隐式共享,使用非常量运算符和函数可能会导致 QList 对数据进行深度复制。
//QList 的值类型必须是可赋值的数据类型。
//这涵盖了大多数常用的数据类型,但编译器不会让您例如将 QWidget 存储为值;
//相反,存储一个 QWidget *。
//。 一些功能有额外的要求;
//例如, indexOf() 和 lastIndexOf() 期望值类型支持 operator==()。 这些要求是按功能记录的。
//与其他容器类一样,QList 提供 Java 风格的迭代器(QListIterator 和 QMutableListIterator)和 STL 风格的迭代器(QList::const_iterator 和 QList::iterator)
//在实践中,迭代器在使用 Qt 和 C++ 标准库提供的通用算法时很方便
//提供 Java 风格的迭代器是为了向后兼容,在编写 C++ 代码时更喜欢 STL 风格的迭代器。
//注意:当调用 QList 的任何非常量方法时
//不能依赖 QList 上的迭代器以及对其中单个元素的引用来保持有效。
//在调用非常量方法之后访问这样的迭代器或引用会导致未定义的行为。
//当需要类似迭代器的功能的稳定性时
//您应该使用索引而不是迭代器,因为它们与 QList 的内部状态无关,因此不会失效。
//除了 QList 之外,Qt 还提供了 QVarLengthArray
//这是一个非常低级的类,功能很少,针对速度进行了优化。
//有关将 Qt 容器相互比较以及与 STL 容器进行比较的详细讨论,请参阅了解 Qt 容器。
//在列表中的索引位置 i 处插入值。 如果 i 为 0,
//该值将添加到列表中。 如果 i 是 size(),则将该值附加到列表中。
/*
QList<QString> list;
list<<"alpha"<<"beta"<<"delta";
list.insert(2,"gamma");
//list:["alpha","beta","gamma","delta"]
*/
//对于大型列表,此操作可能很慢(线性时间)
//因为它需要将索引 i 及以上的所有项目在内存中进一步移动一个位置
//如果您想要一个提供快速 insert() 函数的容器类,请改用 std::list。
//template <typename Args> QList::reference QList::emplace_back(Args &&... args)
//在容器的末尾添加一个新元素。
//这个新元素是使用 args 作为其构造参数就地构造的。
//在容器的末尾添加一个新元素
//这个新元素是使用 args 作为构造参数就地构造的。
//返回对新元素的引用。
/*
QList<QString> list("one","two");
list.emplaceBack(3,'a');
qDebug()<<list;
//list:["one","two","aaa"]
*/
//也可以使用返回的引用访问新创建的对象:
//void QList::prepend(QList::rvalue_ref value)
//在列表的开头插入值。
/*
QList<QString> list;
list.prepend("one");
list.prepend("two");
list.prepend("three");
//list:["three","two","one"]
*/
//在列表末尾插入值。
/*
QList<QString> list;
list.append("one");
list.append("two");
QString three = "three";
list.append(three);
//list:["one","two","three"]
//three:"three"
*/
typedef QPair<QPointF, QString> Data;
typedef QList<Data> DataList;
typedef QList<DataList> DataTable;
QT_USE_NAMESPACE
class ThemeWidget: public QWidget
{
Q_OBJECT
public:
explicit ThemeWidget(QWidget *parent = 0);
~ThemeWidget();
private Q_SLOTS:
void updateUI();
private:
DataTable generateRandomData(int listCount, int valueMax, int valueCount) const;
void populateThemeBox();
void populateAnimationBox();
void populateLegendBox();
void connectSignals();
QChart *createAreaChart() const;
QChart *createBarChart(int valueCount) const;
QChart *createPieChart() const;
QChart *createLineChart() const;
QChart *createSplineChart() const;
QChart *createScatterChart() const;
private:
int m_listCount;
int m_valueMax;
int m_valueCount;
QList<QChartView *> m_charts;
DataTable m_dataTable;
Ui_ThemeWidgetForm *m_ui;
};
#endif /* THEMEWIDGET_H */
themewidget.cpp
#include "themewidget.h"
#include "ui_themewidget.h"
#include <QtCharts/QChartView>
#include <QtCharts/QPieSeries>
#include <QtCharts/QPieSlice>
#include <QtCharts/QAbstractBarSeries>
#include <QtCharts/QPercentBarSeries>
#include <QtCharts/QStackedBarSeries>
#include <QtCharts/QBarSeries>
#include <QtCharts/QBarSet>
#include <QtCharts/QLineSeries>
#include <QtCharts/QSplineSeries>
#include <QtCharts/QScatterSeries>
#include <QtCharts/QAreaSeries>
#include <QtCharts/QLegend>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QSpinBox>
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QGroupBox>
#include <QtWidgets/QLabel>
#include <QtCore/QRandomGenerator>
#include <QtCharts/QBarCategoryAxis>
#include <QtWidgets/QApplication>
#include <QtCharts/QValueAxis>
ThemeWidget::ThemeWidget(QWidget *parent) :
QWidget(parent),
m_listCount(3),
m_valueMax(10),
m_valueCount(7),
m_dataTable(generateRandomData(m_listCount, m_valueMax, m_valueCount)),
m_ui(new Ui_ThemeWidgetForm)
{
m_ui->setupUi(this);
populateThemeBox();
populateAnimationBox();
populateLegendBox();
//create charts
QChartView *chartView;
chartView = new QChartView(createAreaChart());
m_ui->gridLayout->addWidget(chartView, 1, 0);
m_charts << chartView;
chartView = new QChartView(createPieChart());
// Funny things happen if the pie slice labels do not fit the screen, so we ignore size policy
chartView->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
m_ui->gridLayout->addWidget(chartView, 1, 1);
m_charts << chartView;
//![5]
chartView = new QChartView(createLineChart());
m_ui->gridLayout->addWidget(chartView, 1, 2);
//![5]
m_charts << chartView;
chartView = new QChartView(createBarChart(m_valueCount));
m_ui->gridLayout->addWidget(chartView, 2, 0);
m_charts << chartView;
chartView = new QChartView(createSplineChart());
m_ui->gridLayout->addWidget(chartView, 2, 1);
m_charts << chartView;
chartView = new QChartView(createScatterChart());
m_ui->gridLayout->addWidget(chartView, 2, 2);
m_charts << chartView;
// Set defaults
m_ui->antialiasCheckBox->setChecked(true);
// Set the colors from the light theme as default ones
QPalette pal = qApp->palette();
pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
pal.setColor(QPalette::WindowText, QRgb(0x404044));
qApp->setPalette(pal);
updateUI();
}
ThemeWidget::~ThemeWidget()
{
delete m_ui;
}
DataTable ThemeWidget::generateRandomData(int listCount, int valueMax, int valueCount) const
{
DataTable dataTable;
// generate random data
for (int i(0); i < listCount; i++) {
DataList dataList;
qreal yValue(0);
//QRandomGenerator 可用于从高质量随机数生成器生成随机值。
//QRandomGenerator::global() 返回 QRandomGenerator 的全局实例
//Qt 将确保安全播种。 这个对象是线程安全的,可以在大多数用途中共享,并且总是从 QRandomGenerator::system()
//批量数据
//在确定性模式下运行时, QRandomGenerator 可用于批量数据生成。
//事实上,建议不需要加密安全或真正随机数据的应用程序使用常规 QRandomGenerator 而不是
//QRandomGenerator::system() 来满足其随机数据需求。
//为了方便使用,QRandomGenerator 提供了一个可以方便使用的全局对象,如下例所示:
/*
int x = QRandomGenerator::global()->generate();
int y = QRandomGenerator::global()->generate();
int w = QRandomGenerator::global()->bounded(16384);
int h = QRandomGenerator::global()->bounded(16384);
*/
for (int j(0); j < valueCount; j++) {
yValue = yValue + QRandomGenerator::global()->bounded(valueMax / (qreal) valueCount);
QPointF value((j + QRandomGenerator::global()->generateDouble()) * ((qreal) m_valueMax / (qreal) valueCount),
yValue);
QString label = "Slice " + QString::number(i) + ":" + QString::number(j);
dataList << Data(value, label);
}
dataTable << dataList;
}
return dataTable;
}
//enum QChart::ChartTheme
//此枚举描述图表使用的主题。
//主题是一个内置的 UI 样式相关设置集合
//应用于图表的所有视觉元素,
//例如颜色、钢笔、画笔和系列字体,以及轴、标题和图例。
//图表主题示例说明了如何使用主题。
//注意:更改主题将覆盖之前应用于该系列的所有自定义设置。
//QChart::ChartThemeLight0 浅色主题,默认主题。
//QChart::ChartThemeBlueCerulean1天蓝色主题。
//QChart::ChartThemeDark2黑暗主题。
//QChart::ChartThemeBrownSand3沙棕色主题。
//QChart::ChartThemeBlueNcs4自然色系(NCS)蓝色主题。
//QChart::ChartThemeHighContrast5高对比度主题。
//QChart::ChartThemeBlueIcy6冰蓝色主题。
//QChart::ChartThemeQt7 Qt 主题。
void ThemeWidget::populateThemeBox()
{
// add items to theme combobox
m_ui->themeComboBox->addItem("Light", QChart::ChartThemeLight);
m_ui->themeComboBox->addItem("Blue Cerulean", QChart::ChartThemeBlueCerulean);
m_ui->themeComboBox->addItem("Dark", QChart::ChartThemeDark);
m_ui->themeComboBox->addItem("Brown Sand", QChart::ChartThemeBrownSand);
m_ui->themeComboBox->addItem("Blue NCS", QChart::ChartThemeBlueNcs);
m_ui->themeComboBox->addItem("High Contrast", QChart::ChartThemeHighContrast);
m_ui->themeComboBox->addItem("Blue Icy", QChart::ChartThemeBlueIcy);
m_ui->themeComboBox->addItem("Qt", QChart::ChartThemeQt);
}
void ThemeWidget::populateAnimationBox()
{
// add items to animation combobox
m_ui->animatedComboBox->addItem("No Animations", QChart::NoAnimation);
m_ui->animatedComboBox->addItem("GridAxis Animations", QChart::GridAxisAnimations);
m_ui->animatedComboBox->addItem("Series Animations", QChart::SeriesAnimations);
m_ui->animatedComboBox->addItem("All Animations", QChart::AllAnimations);
}
void ThemeWidget::populateLegendBox()
{
// add items to legend combobox
m_ui->legendComboBox->addItem("No Legend ", 0);
m_ui->legendComboBox->addItem("Legend Top", Qt::AlignTop);
m_ui->legendComboBox->addItem("Legend Bottom", Qt::AlignBottom);
m_ui->legendComboBox->addItem("Legend Left", Qt::AlignLeft);
m_ui->legendComboBox->addItem("Legend Right", Qt::AlignRight);
}
//面积序列用于显示定量数据。
//它基于线系列,以颜色强调边界线之间的区域。
//由于面积系列是基于线系列的,
//所以QAreaSeries 构造函数需要一个QLineSeries 实例
//它定义了面积的上边界
//面积图默认以绘图区域的底部为下边界绘制
//可以用另一条线指定下边界
//而不是绘图区域的底部
//在这种情况下,应该使用两个 QLineSeries 实例初始化 QAreaSeries。
QChart *ThemeWidget::createAreaChart() const
{
QChart *chart = new QChart();
chart->setTitle("Area chart");
// The lower series initialized to zero values
QLineSeries *lowerSeries = 0;
QString name("Series ");
int nameIndex = 0;
for (int i(0); i < m_dataTable.count(); i++) {
QLineSeries *upperSeries = new QLineSeries(chart);
for (int j(0); j < m_dataTable[i].count(); j++) {
Data data = m_dataTable[i].at(j);
if (lowerSeries) {
const auto &points = lowerSeries->points();
upperSeries->append(QPointF(j, points[i].y() + data.first.y()));
} else {
upperSeries->append(QPointF(j, data.first.y()));
}
}
QAreaSeries *area = new QAreaSeries(upperSeries, lowerSeries);
area->setName(name + QString::number(nameIndex));
nameIndex++;
chart->addSeries(area);
lowerSeries = upperSeries;
}
chart->createDefaultAxes();
chart->axes(Qt::Horizontal).first()->setRange(0, m_valueCount - 1);
chart->axes(Qt::Vertical).first()->setRange(0, m_valueMax);
// Add space to label to add space between labels and axis
QValueAxis *axisY = qobject_cast<QValueAxis*>(chart->axes(Qt::Vertical).first());
Q_ASSERT(axisY);
axisY->setLabelFormat("%.1f ");
return chart;
}
QChart *ThemeWidget::createBarChart(int valueCount) const
{
Q_UNUSED(valueCount);
QChart *chart = new QChart();
chart->setTitle("Bar chart");
//添加到系列中的每个条形集为每个堆叠的条形贡献一个单独的段。
QStackedBarSeries *series = new QStackedBarSeries(chart);
for (int i(0); i < m_dataTable.count(); i++) {
QBarSet *set = new QBarSet("Bar set " + QString::number(i));
for (const Data &data : m_dataTable[i])
*set << data.first.y();
series->append(set);
}
chart->addSeries(series);
chart->createDefaultAxes();
chart->axes(Qt::Vertical).first()->setRange(0, m_valueMax * 2);
// Add space to label to add space between labels and axis
QValueAxis *axisY = qobject_cast<QValueAxis*>(chart->axes(Qt::Vertical).first());
Q_ASSERT(axisY);
axisY->setLabelFormat("%.1f ");
return chart;
}
QChart *ThemeWidget::createLineChart() const
{
//![1]
QChart *chart = new QChart();
chart->setTitle("Line chart");
//![1]
//![2]
QString name("Series ");
int nameIndex = 0;
for (const DataList &list : m_dataTable) {
QLineSeries *series = new QLineSeries(chart);
for (const Data &data : list)
series->append(data.first);
series->setName(name + QString::number(nameIndex));
nameIndex++;
chart->addSeries(series);
}
//![2]
//![3]
chart->createDefaultAxes();
chart->axes(Qt::Horizontal).first()->setRange(0, m_valueMax);
chart->axes(Qt::Vertical).first()->setRange(0, m_valueCount);
//![3]
//![4]
// Add space to label to add space between labels and axis
QValueAxis *axisY = qobject_cast<QValueAxis*>(chart->axes(Qt::Vertical).first());
Q_ASSERT(axisY);
axisY->setLabelFormat("%.1f ");
//![4]
return chart;
}
QChart *ThemeWidget::createPieChart() const
{
QChart *chart = new QChart();
chart->setTitle("Pie chart");
QPieSeries *series = new QPieSeries(chart);
for (const Data &data : m_dataTable[0]) {
QPieSlice *slice = series->append(data.second, data.first.y());
if (data == m_dataTable[0].first()) {
// Show the first slice exploded with label
slice->setLabelVisible();
slice->setExploded();
slice->setExplodeDistanceFactor(0.5);
}
}
series->setPieSize(0.4);
chart->addSeries(series);
return chart;
}
QChart *ThemeWidget::createSplineChart() const
{
QChart *chart = new QChart();
chart->setTitle("Spline chart");
QString name("Series ");
int nameIndex = 0;
for (const DataList &list : m_dataTable) {
QSplineSeries *series = new QSplineSeries(chart);
for (const Data &data : list)
series->append(data.first);
series->setName(name + QString::number(nameIndex));
nameIndex++;
chart->addSeries(series);
}
chart->createDefaultAxes();
chart->axes(Qt::Horizontal).first()->setRange(0, m_valueMax);
chart->axes(Qt::Vertical).first()->setRange(0, m_valueCount);
// Add space to label to add space between labels and axis
QValueAxis *axisY = qobject_cast<QValueAxis*>(chart->axes(Qt::Vertical).first());
Q_ASSERT(axisY);
axisY->setLabelFormat("%.1f ");
return chart;
}
QChart *ThemeWidget::createScatterChart() const
{
// scatter chart
QChart *chart = new QChart();
chart->setTitle("Scatter chart");
QString name("Series ");
int nameIndex = 0;
for (const DataList &list : m_dataTable) {
QScatterSeries *series = new QScatterSeries(chart);
for (const Data &data : list)
series->append(data.first);
series->setName(name + QString::number(nameIndex));
nameIndex++;
chart->addSeries(series);
}
chart->createDefaultAxes();
chart->axes(Qt::Horizontal).first()->setRange(0, m_valueMax);
chart->axes(Qt::Vertical).first()->setRange(0, m_valueCount);
// Add space to label to add space between labels and axis
QValueAxis *axisY = qobject_cast<QValueAxis*>(chart->axes(Qt::Vertical).first());
Q_ASSERT(axisY);
axisY->setLabelFormat("%.1f ");
return chart;
}
void ThemeWidget::updateUI()
{
//![6]
QChart::ChartTheme theme = static_cast<QChart::ChartTheme>(
m_ui->themeComboBox->itemData(m_ui->themeComboBox->currentIndex()).toInt());
//![6]
const auto charts = m_charts;
if (!m_charts.isEmpty() && m_charts.at(0)->chart()->theme() != theme) {
for (QChartView *chartView : charts) {
//![7]
chartView->chart()->setTheme(theme);
//![7]
}
// Set palette colors based on selected theme
//![8]
QPalette pal = window()->palette();
if (theme == QChart::ChartThemeLight) {
pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
pal.setColor(QPalette::WindowText, QRgb(0x404044));
//![8]
} else if (theme == QChart::ChartThemeDark) {
pal.setColor(QPalette::Window, QRgb(0x121218));
pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
} else if (theme == QChart::ChartThemeBlueCerulean) {
pal.setColor(QPalette::Window, QRgb(0x40434a));
pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
} else if (theme == QChart::ChartThemeBrownSand) {
pal.setColor(QPalette::Window, QRgb(0x9e8965));
pal.setColor(QPalette::WindowText, QRgb(0x404044));
} else if (theme == QChart::ChartThemeBlueNcs) {
pal.setColor(QPalette::Window, QRgb(0x018bba));
pal.setColor(QPalette::WindowText, QRgb(0x404044));
} else if (theme == QChart::ChartThemeHighContrast) {
pal.setColor(QPalette::Window, QRgb(0xffab03));
pal.setColor(QPalette::WindowText, QRgb(0x181818));
} else if (theme == QChart::ChartThemeBlueIcy) {
pal.setColor(QPalette::Window, QRgb(0xcee7f0));
pal.setColor(QPalette::WindowText, QRgb(0x404044));
} else {
pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
pal.setColor(QPalette::WindowText, QRgb(0x404044));
}
window()->setPalette(pal);
}
// Update antialiasing
//![11]
bool checked = m_ui->antialiasCheckBox->isChecked();
for (QChartView *chart : charts)
chart->setRenderHint(QPainter::Antialiasing, checked);
//![11]
// Update animation options
//![9]
QChart::AnimationOptions options(
m_ui->animatedComboBox->itemData(m_ui->animatedComboBox->currentIndex()).toInt());
if (!m_charts.isEmpty() && m_charts.at(0)->chart()->animationOptions() != options) {
for (QChartView *chartView : charts)
chartView->chart()->setAnimationOptions(options);
}
//![9]
// Update legend alignment
//![10]
Qt::Alignment alignment(
m_ui->legendComboBox->itemData(m_ui->legendComboBox->currentIndex()).toInt());
if (!alignment) {
for (QChartView *chartView : charts)
chartView->chart()->legend()->hide();
} else {
for (QChartView *chartView : charts) {
chartView->chart()->legend()->setAlignment(alignment);
chartView->chart()->legend()->show();
}
}
//![10]
}