How to free RAM after using QChartView?
-
Hey,
I'm using a simple code to draw a chart, here an example - just the values of the QLineSeries are faked:
QLineSeries *series = new QLineSeries(); series->append(0, 1); series->append(1, 2); series->append(2, 5); series->append(3, 3); QChart *chart = new QChart(); chart->legend()->hide(); chart->addSeries(series); chart->createDefaultAxes(); QChartView *chartView = new QChartView(chart); chartView->setRenderHint(QPainter::Antialiasing); chartView->resize(800, 600); chartView->show();
I now have the problem that I use more RAM with every call. What's the correct way to handle it?
I tried to save the pointer of the Chart, ChartView and LineSeries and constantly checking if the window is still open/active. If the window is closed, I tried to use the deleteLater function but this crashs my application.Can someone help please? Thanks
-
@HTWAMD said in How to free RAM after using QChartView?:
What's the correct way to handle it?
You're creating objects without deleting them - so delete them and the memory will be freed - C++ basics.
-
Well yes, sure. But like I said using the delete or deleteLater function isn't working. It crashes the whole application.
chartView->deleteLater(); chart->deleteLater(); //Or delete chartView; delete chart;
I tried these function after the window of the chart is closed but no success.
-
@HTWAMD said in How to free RAM after using QChartView?:
It crashes the whole application.
Because you delete it twice:
https://doc.qt.io/qt-5/qchartview.html#QChartView-1 : The ownership of the chart is passed to the chart view.
And please provide a minimal example where it crashes - you code above doesn't show where/how you delete the objects.
-
I tried some more stuff but I' cant deal with the Chart stuff :(
Here is - basically - my code I use (header + source, the ui contains just a widget and two spinboxes):
namespace Ui { class EventDrawer; } class EventDrawer : public QWidget { Q_OBJECT public: explicit EventDrawer(QWidget *parent, QTableWidget* listEvents); ~EventDrawer(); void draw_chart(); public slots: void closeEvent (QCloseEvent *event); private slots: void on_spinBox_min_valueChanged(int arg1); void on_spinBox_max_valueChanged(int arg1); private: Ui::EventDrawer *ui; QChart* Chart; QChartView* chartView; QVBoxLayout* LayoutChart; QLineSeries* series; QTableWidget* table_ptr; bool init; int min_value; int max_value; }; #endif // EVENTDRAWER_H #include "eventdrawer.h" #include "ui_eventdrawer.h" EventDrawer::EventDrawer(QWidget *parent, QTableWidget* listEvents) : ui(new Ui::EventDrawer) { ui->setupUi(this); this->setStyleSheet(parent->styleSheet()); init = true; min_value = 0; max_value = 0; table_ptr = listEvents; draw_chart(); init = false; } EventDrawer::~EventDrawer() { delete ui; } void EventDrawer::closeEvent (QCloseEvent *event) { delete ui->widget->layout(); event->accept(); } void EventDrawer::draw_chart() { int counter = 1; QMap<QString, int> InfoTypes; for (int i=0; i < table_ptr->rowCount(); i++) { int value = i; QString info_type = table_ptr->item(value, 1)->text(); if (InfoTypes[info_type] == 0) InfoTypes[info_type] = counter++; } int event_type_count = InfoTypes.count(); if (event_type_count == 0) return; int min = 9999999; int max = -9999999; series = new QLineSeries[event_type_count]; for (int i=0; i < table_ptr->rowCount(); i++) { int value = i; if (ui->checkBox_oldFirst->isChecked()) value = (table_ptr->rowCount()-1) - i; QString info_type = table_ptr->item(value, 1)->text(); float info_value = table_ptr->item(value, 2)->text().toFloat(); if (info_value < min) min = info_value; if (info_value > max) max = info_value; if (ui->checkBox_dateAxis->isChecked()) { QDateTime timestamp = QDateTime::fromString(table_ptr->item(value, 3)->text(), "yyyy-MM-dd hh:mm:ss.zzz"); series[InfoTypes[info_type]-1].append(timestamp.toMSecsSinceEpoch(), info_value); } else { series[InfoTypes[info_type]-1].append(i, info_value); } series[InfoTypes[info_type]-1].setName(info_type); } Chart = new QChart(); for (int i=0; i < event_type_count; i++) Chart->addSeries(&series[i]); if (ui->checkBox_dateAxis->isChecked()) { QDateTimeAxis *axisX = new QDateTimeAxis; axisX->setTickCount(14); axisX->setFormat("MM.dd hh:mm:ss"); axisX->setTitleText("Date"); Chart->addAxis(axisX, Qt::AlignBottom); series->attachAxis(axisX); Chart->axisX()->setTitleText("Date"); QValueAxis *axisY = new QValueAxis; axisY->setLabelFormat("%i"); Chart->addAxis(axisY, Qt::AlignLeft); series->attachAxis(axisY); } else { Chart->createDefaultAxes(); Chart->axisX()->setRange(0, table_ptr->rowCount()); } if (min_value != 0 || max_value != 0) { Chart->axisY()->setRange(min_value, max_value); } else { ui->spinBox_max->setValue(max); ui->spinBox_min->setValue(min); } chartView = new QChartView(Chart); chartView->setRenderHint(QPainter::Antialiasing); LayoutChart = new QVBoxLayout(); LayoutChart->addWidget(chartView); ui->widget->setLayout(LayoutChart); } void EventDrawer::on_spinBox_min_valueChanged(int arg1) { if (init) return; min_value = arg1; Chart->axisY()->setRange(min_value, max_value); } void EventDrawer::on_spinBox_max_valueChanged(int arg1) { if (init) return; max_value = arg1; Chart->axisY()->setRange(min_value, max_value); }
What I would like to do now, is to delete / free the ram when the window is closed. So if the closeEvent function is called, delete the chartView, Chart, Series.
Could someone please show me how to do this? -
Again: please provide a minimal, compilable example if you think there is a crash and / or a memleak. Delete your chartView in the dtor and the memory will be freed afaics.
-
Okay I made a very short, compilable example, here is the download link:
https://filetransfer.io/data-package/wck4NloPCompile, run the application, click draw chart, close the window, crash.
Can you or anyone please tell me how to modify the code / the dtor to avoid the crash? -
First in the dtor only 'delete ui' is needed - the rest is deleted due to parent child relationships.
Second please take a look at
QLineSeries *series = new QLineSeries[event_type_count]; ... Chart->addSeries(&series[i]);
since addSeries() is taking ownership, it's later also calling 'delete &series[i]' - this can't work.
Use a QVector<QLineSeries*>, no need to hold it as member (at least not in your testcase).
-
@HTWAMD Then please mark this topic as solved, thx.