How to create a LineChart without knowing the amount of needed QLineSeries until runtime?
-
I am attempting to make a LineChart, and I do not know the amount of QLineSeries objects I need until runtime. In the actual problem, I read a file with a random amount of tools in it, and I do not know how many tools are in the file until reading it. As well, it can be different every time.
So, I made a more simple problem to work with (code is below)
void MainWindow::testQtCharts() { QtCharts::QLineSeries *lineseries = new QtCharts::QLineSeries(); QtCharts::QChart *chart = new QtCharts::QChart(); chart->setTitle("Title"); for(int i = 1; i < 6; i++) { lineseries = new QtCharts::QLineSeries(); lineseries->append(QPoint(0, i * 2)); lineseries->append(QPoint(1, i * 2)); lineseries->append(QPoint(2, i * 2)); lineseries->append(QPoint(3, i * 2)); lineseries->append(QPoint(4, i * 2)); lineseries->append(QPoint(5, i * 2)); lineseries->setName(QString::number(i)); chart->addSeries(lineseries); lineseries->clear(); } QStringList categories; categories << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "Jun"; QtCharts::QBarCategoryAxis *axisX = new QtCharts::QBarCategoryAxis(); axisX->append(categories); chart->addAxis(axisX, Qt::AlignBottom); lineseries->attachAxis(axisX); axisX->setRange(QString("Jan"), QString("Jun")); QtCharts::QValueAxis *axisY = new QtCharts::QValueAxis(); chart->addAxis(axisY, Qt::AlignLeft); lineseries->attachAxis(axisY); axisY->setRange(0, 20); chart->legend()->setVisible(true); chart->legend()->setAlignment(Qt::AlignBottom); QtCharts::QChartView *chartView = new QtCharts::QChartView(chart); chartView->setRenderHint(QPainter::Antialiasing); // Saving the graph itself QPixmap pixmap = chartView->grab(); pixmap.save("C:/Users/Admin/test.png"); }
Outputted PNG:
A lot of this code comes from the documentation for Line and BarChart example on Qt (https://doc.qt.io/qt-6/qtcharts-lineandbar-example.html). I am using this specific example, because I need days as the X Axis.
The issue with the code above, is I do not get any plots. I had originally put the
lineseries = new QtCharts::QLineSeries();
line at the bottom of the for loop, but that had given me an error in the Application Output stating
Series not in the chart. Please addSeries to chart first.
If I can figure out how to make the series get added to the chart, and then clear the series and add a new one this would work perfectly..not sure if it is something simple I am missing.
I see that the legend is being created properly, so the QLineSeries must be saved, but the data does not seem to be getting in there correctly...Thanks in advance!
-
@orsini29
For when you want to calllineseries = new QLineSeries();
I am a little lost (and I didn't look at it).If you take it out entirely from within the
for (i < 6)
loop then you will have just oneQLineSeries
, the one at the first line of the function. (You would also need to callchart->addSeries(lineseries);
on that one outside the loop, at present that firstQLIneSeries
is pointless/a memory leak.) That series would have 5 * 6 == 30 points on it. Is that what you want?But you talk about "The purpose is to have different lines/coloring for each line". That implies to me you do want multiple, separate line series, each with their own points and color? In that case you do want
new QLineSeries
created each time round the loop, so you end up with 5 lines (and get rid of the wasted one outside the loop).Only you know how many line series you want, and how many points at what coordinates on each line.
-
@orsini29 said in How to create a LineChart without knowing the amount of needed QLineSeries until runtime?:
The issue with the code above, is I do not get any plots.
chart->addSeries(lineseries); lineseries->clear();
What do you think the second line does?
-
Yeah stupid mistake on my part. So then, if you take out the clear function, I would assume the
lineseries = new QLineSeries();
Should be take out as well for the same reasoning being you’d be recreating the object as new. So therefore, wouldn’t the series end up being treated as a single line in the legend? The purpose is to have different lines/coloring for each line, obviously for the user to be able to differentiate between the multiple different things being plotted.
I will check this out once I get back to my computer, I am currently not by it. Sorry if this is an obvious answer, it stumped me. I get stuck often and tend to overlook these obvious things..as you showed me above
Thanks!
Edit: also, to explain my thought process (which I now see obviously why it was wrong), I was clearing the obj because I didn’t want them to all be plotted as the same line, but then I’m clearing anything within the object so there isn’t even any data in there…
Edit…again: wouldn’t actually just taking out those two lines I mentioned in my comment, solve the problem entirely?
-
@orsini29
For when you want to calllineseries = new QLineSeries();
I am a little lost (and I didn't look at it).If you take it out entirely from within the
for (i < 6)
loop then you will have just oneQLineSeries
, the one at the first line of the function. (You would also need to callchart->addSeries(lineseries);
on that one outside the loop, at present that firstQLIneSeries
is pointless/a memory leak.) That series would have 5 * 6 == 30 points on it. Is that what you want?But you talk about "The purpose is to have different lines/coloring for each line". That implies to me you do want multiple, separate line series, each with their own points and color? In that case you do want
new QLineSeries
created each time round the loop, so you end up with 5 lines (and get rid of the wasted one outside the loop).Only you know how many line series you want, and how many points at what coordinates on each line.
-
But you talk about "The purpose is to have different lines/coloring for each line". That implies to me you do want multiple, separate line series, each with their own points and color?
Yes.
In that case you do want new QLineSeries created each time round the loop, so you end up with 5 lines (and get rid of the wasted one outside the loop).
Okay, thank you. I did this and with a little bit of refactoring I got it to work as expected. Appreciate the assistance!
-
-
-
-