Exploring Qt Charts
The core part is ready. It's now time to create a UI for this project, and Qt Charts can help us with this task. Qt Charts is a module that provides a set of easy-to-use chart components, such as line chart, area chart, spline chart, pie chart, and so on.
Qt Charts was previously a commercial-only Qt module. Since Qt 5.7, the module is now included in Qt on GPLv3 license for open source users. If you are stuck on Qt 5.6, you can build the module by yourself from sources. More information can be found at https://github.com/qtproject/qtcharts.
The aim now is to create two Qt widgets, CpuWidget and MemoryWidget, to display nice Qt charts of the CPU and the memory used. These two widgets will share a lot of common tasks, so we will first create an abstract class, SysInfoWidget:
Then the two actual widgets will inherit from the SysInfoWidget class and perform their specific tasks.
Create a new C++ class called SysInfoWidget with QWidget as a base class. Some enhancements must be processed in the SysInfoWidget.h file:
#include <QWidget> #include <QTimer> #include <QtCharts/QChartView> class SysInfoWidget : public QWidget { Q_OBJECT public: explicit SysInfoWidget(QWidget *parent = 0, int startDelayMs = 500, int updateSeriesDelayMs = 500); protected: QtCharts::QChartView& chartView(); protected slots: virtual void updateSeries() = 0; private: QTimer mRefreshTimer; QtCharts::QChartView mChartView; };
The QChartView is the generic widget that can display many types of chart. This class will handle the layout and display the QChartView. A QTimer will call the slot function updateSeries() regularly. As you can see, this is a pure virtual slot. That is the reason why the SysInfoWidget class is abstract. The slot updateSeries() will be overridden by child classes to retrieve a system value and define how the chart should be drawn. Note that the parameters startDelayMs and updateSeriesDelayMs have default values that can be customized by the caller if required.
We can now proceed to the SysInfoWidget.cpp file to correctly prepare this SysInfoWidget class before creating the child widgets:
#include <QVBoxLayout> using namespace QtCharts; SysInfoWidget::SysInfoWidget(QWidget *parent, int startDelayMs, int updateSeriesDelayMs) : QWidget(parent), mChartView(this) { mRefreshTimer.setInterval(updateSeriesDelayMs); connect(&mRefreshTimer, &QTimer::timeout, this, &SysInfoWidget::updateSeries); QTimer::singleShot(startDelayMs, [this] { mRefreshTimer.start(); }); mChartView.setRenderHint(QPainter::Antialiasing); mChartView.chart()->legend()->setVisible(false); QVBoxLayout* layout = new QVBoxLayout(this); layout->addWidget(&mChartView); setLayout(layout); } QChartView& SysInfoWidget::chartView() { return mChartView; }
All tasks in the SysInfoWidget constructor are common tasks required by the child widgets, CpuWidget, and MemoryWidget. The first step is the mRefreshTimer initialization to define the timer interval and the slot to call whenever a timeout signal is triggered. Then the static function QTimer::singleShot() will start the real timer after a delay defined by startDelayMs. Here again, Qt combined with lambda functions will give us a powerful code in just a few lines. The next part enables the antialiasing to smooth the chart drawing. We hide the chart's legend to get a minimalist display. The last part handles the layout to display the QChartView widget in our SysInfoWidget class.