Qt setUseOpenGL(true) and removeSeries() do not update QChart - c++

The Problem
I'm using a Qt LineChart, this QLineChart can load and remove data without a problem on CPU rendering. However, QChart removeSeries() does not update my QLineChart properly when using setUseOpenGL(true). The removed data is still visible on the QChart. Strangely, when hovering the mouse over the QChart, the QChart is updated and data is removed.
Expected Result
Update QChart after calling removeSeries().
Observed Result
QChart is not updated.
What I've tried
Call ChartView repaint() -- no effect
Emit custom QEvent to simulate mouse hover over QChart -- no effect
Set Widget which contains QChartView to FullViewportUpdate -- no effect
I'm all out of ideas. All suggestions are welcome. Relevant code:
QLineSeries *series3= data->getScanLineSeries();
series3->setUseOpenGL(true);
if(data->getLineSeriesOnChart() == false)
...
{
chart->addSeries(series3);
data->setLineSeriesOnChart(true);
std::cout << "Series added to chart.";
qDebug() << QString("Series added to chart");
}
else
{
chart->removeSeries(series3);
data->setLineSeriesOnChart(false);
qDebug() << QString("ERROR: this series was already on the chart, removing QLineSeries");
return chart;
}
...
(axes handling)
return chart;

I have checked the problem, and now I have a temporary solution and not very elegant, it may serve to advance, I have noticed that the chart is updated when you resize the chart, then this is a code that can help you:
chartView->resize(chartView->size() + QSize(1, 1));
chartView->resize(chartView->size() - QSize(1, 1));
I'll keep on looking for a better solution
Example:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QLineSeries *series = new QLineSeries();
series->append(0, 6);
series->append(2, 4);
series->append(3, 8);
series->append(7, 4);
series->append(10, 5);
*series << QPointF(11, 1) << QPointF(13, 3) << QPointF(17, 6) << QPointF(18, 3) << QPointF(20, 2);
series->setUseOpenGL(true);
QChart *chart = new QChart();
chart->legend()->hide();
chart->addSeries(series);
chart->createDefaultAxes();
chart->setTitle("Simple line chart example");
QChartView *chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
QTimer timer;
QObject::connect(&timer, &QTimer::timeout, [chart, series, chartView](){
qDebug()<<chart->series();
if(!chart->series().isEmpty())
chart->removeSeries(series);
else
chart->addSeries(series);
chartView->resize(chartView->size()+QSize(1, 1));
chartView->resize(chartView->size()-QSize(1, 1));
});
timer.start(1000);
QMainWindow window;
window.setCentralWidget(chartView);
window.resize(400, 300);
window.show();
return a.exec();
}

Related

How to fix display problem when I use QGraphicsView and QGraphicsEffect together in Qt?

I have a problem when use QGraphicsView and QGraphicsBlurEffect in my project. When I put them together, my program does not work normally. I wrote a tiny program to reproduce this problem.
The Widget class is inherited from QGraphicsView.
Widget::Widget(QWidget *parent)
: QGraphicsView(parent)
{
scene = new QGraphicsScene(this);
this->setScene(scene);
label = new QLabel;
QPixmap pixmap = QPixmap("../partly_cloudy.png").scaledToWidth(200);
label->setPixmap(pixmap);
label->setGeometry(100,100, pixmap.width(), pixmap.height());
label->setStyleSheet("border:3px;border-color: rgb(255, 100, 0); border-style:solid;");
/* ********image won't show when adding following comment code********
QGraphicsBlurEffect *blur = new QGraphicsBlurEffect;
blur->setBlurRadius(10);
label->setGraphicsEffect(blur);
******* */
QGraphicsProxyWidget *proxyWidget = new QGraphicsProxyWidget;
proxyWidget->setWidget(label);
proxyWidget->setPos(10,10);
scene->addItem(proxyWidget);
}
and main.cpp is as follows.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
This is a screenshot when QGraphicsBlurEffect is not used.
However, this is a screenshot when QLabel uses setGraphicsEffect() to bind blur effect.
To solve this problem, I tried to use a QWidget to wrap QLabel. When I did this, QLabel was rendered. However, it seems to be bounded by a rectangle area.
Widget::Widget(QWidget *parent)
: QGraphicsView(parent)
{
scene = new QGraphicsScene(this);
this->setScene(scene);
/* ********/
container = new QWidget;
container->setStyleSheet("border:3px;border-color: blue; border-style:solid;");
/******** */
label = new QLabel(container);
QPixmap pixmap = QPixmap("../partly_cloudy.png").scaledToWidth(200);
label->setPixmap(pixmap);
label->setGeometry(100,100, pixmap.width(), pixmap.height());
label->setStyleSheet("border:3px;border-color: red; border-style:solid;");
QGraphicsBlurEffect *blur = new QGraphicsBlurEffect;
blur->setBlurRadius(10);
label->setGraphicsEffect(blur);
QGraphicsProxyWidget *proxyWidget = new QGraphicsProxyWidget;
proxyWidget->setWidget(container);
proxyWidget->setPos(80,80);
qDebug() << proxyWidget->boundingRect();
scene->addItem(proxyWidget);
this->setSceneRect(0,0,640,480);
}
The screenshot of the result is.
I tried to set proxyWidget position to {0,0}, and it works normally. it seems that the position of effect rectangle will not influenced by proxyWidget position.
By the way, the version of Qt is 5.14.2.
I've searched for a long time on net. But no use. Please help or try to give some ideas how to achieve this.

How to get chart view in a widget

here I get a chart result in window. I get this source code in Qt official page. And i get some number result in this program and how I get the result in a widget
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QLineSeries *series0 = new QLineSeries();
QLineSeries *series1 = new QLineSeries();
*series0 << QPointF(2.3,5)<<QPointF(-11,4)<<QPointF(-8,3.2)<<QPointF(-9,7.2);
QAreaSeries *series = new QAreaSeries(series0, series1);
series->setName("Area Enclosed");
QPen pen(0x059605);
pen.setWidth(2);
series->setPen(pen);
QLinearGradient gradient(QPointF(0, 10), QPointF(0, 10));
gradient.setColorAt(0.0, 0x26f626);
gradient.setColorAt(1.0, 0x26f626);
gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
series->setBrush(gradient);
QChart *chart = new QChart();
chart->addSeries(series);
chart->setTitle("hello world");
chart->createDefaultAxes();
chart->axes(Qt::Horizontal).first()->setRange(-15, 15);
chart->axes(Qt::Vertical).first()->setRange(-15, 15);
chart->resize(400,400);
QChartView *chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
QMainWindow window;
window.setCentralWidget(chartView);
window.resize(600, 600);
window.show();
return a.exec();
}
how i get a result in the widget view

QPolarChart hide radial tick labels

I have created a QPolarChart and I want to hide the radial tick labels but leave the tick circles. I simply want to get rid of the text which shows "0.0", "20.0" and so on. I tried to change the label format but this did not work.
Here is a minimal example of what I tried:
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtCharts/QChartView>
#include <QtCharts/QLineSeries>
#include <QtCharts/QPolarChart>
#include <QtCharts/QValueAxis>
QT_CHARTS_USE_NAMESPACE
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPolarChart *chart = new QPolarChart();
QValueAxis *angularAxis = new QValueAxis();
angularAxis->setTickCount(13);
angularAxis->setLabelFormat("%d");
angularAxis->setRange(0, 361);
chart->addAxis(angularAxis, QPolarChart::PolarOrientationAngular);
QValueAxis *radialAxis = new QValueAxis();
radialAxis->setTickCount(10);
radialAxis->setLabelFormat(""); // <-- what do I have to add here?
radialAxis->setRange(0, 90);
chart->addAxis(radialAxis, QPolarChart::PolarOrientationRadial);
chart->legend()->setVisible(false);
QLineSeries *series = new QLineSeries();
*series << QPointF(0, 0) << QPointF(90, 22.5) << QPointF(180, 45) << QPointF(270, 67.5) << QPointF(360, 90);
chart->addSeries(series);
QChartView *chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
chart->legend()->hide();
QMainWindow window;
window.setCentralWidget(chartView);
window.resize(400, 400);
window.show();
return a.exec();
}
This is how the result looks like.
I want to get rid of the radial axis labels ("0.0", "10.0" ... "90.0")
The trick is to set as labelFormat to " " or an invalid format like "#":
radialAxis->setLabelFormat(" ");
# or radialAxis->setLabelFormat("#");
radialAxis->setLabelsVisible(false);

Changing text color for each label in QCategoryAxis

Is there a way to assign a color for each label in a QCategoryAxis?
I know I can have a legend, but I prefer setting the colors on the axis to match the colors of the lines I have. I want to change the color of the markers (text of the categories) themselves, not the ticks. Notice that I want to set a different color for each axis label.
Tried using axisY.setLabelsBrush(QBrush(Qt::red));
But this sets the same color for all the labels.
Using Qt 5.10
the labels of QCategoryAxis are QGraphicsTextItem so they support HTML, so you could pass the color through that method:
#include <QApplication>
#include <QMainWindow>
#include <QtCharts>
QT_CHARTS_USE_NAMESPACE
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QLineSeries *series = new QLineSeries();
*series << QPointF(0, 6) << QPointF(9, 4) << QPointF(15, 20) << QPointF(25, 12) << QPointF(29, 26);
QChart *chart = new QChart();
chart->legend()->hide();
chart->addSeries(series);
QCategoryAxis *axisX = new QCategoryAxis();
QCategoryAxis *axisY = new QCategoryAxis();
// Customize axis label font
QFont labelsFont;
labelsFont.setPixelSize(12);
axisX->setLabelsFont(labelsFont);
axisY->setLabelsFont(labelsFont);
// Customize axis colors
QPen axisPen(QRgb(0xd18952));
axisPen.setWidth(2);
axisX->setLinePen(axisPen);
axisY->setLinePen(axisPen);
axisX->append("<span style=\"color: #339966;\">low</span>", 10);
axisX->append("<span style=\"color: #330066;\">optimal</span>", 20);
axisX->append("<span style=\"color: #55ff66;\">high</span>", 30);
axisX->setRange(0, 30);
axisY->append("<font color=\"red\">slow</font>", 10);
axisY->append("<font color=\"green\">med</font>", 20);
axisY->append("<span style=\"color: #ffff00;\">fast</span>", 30);
axisY->setRange(0, 30);
chart->setAxisX(axisX, series);
chart->setAxisY(axisY, series);
QChartView *chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
QMainWindow window;
window.setCentralWidget(chartView);
window.resize(400, 300);
window.show();
return a.exec();
}

QChart in a QTextDocument

I want to generate a pdf report containing text and a QChart. I currently use the QTextDocument and add the chart into it as an image, then I use the QPdfWriter to export to pdf.
#include <QtGui>
#include <QtCore>
#include <QApplication>
#include <QtCharts/QChartView>
#include <QtCharts/QLineSeries>
using namespace QtCharts;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Create a chart
QLineSeries *series = new QLineSeries();
series->append(0,0);
series->append(1,1);
QChart *chart = new QChart();
chart->addSeries(series);
chart->createDefaultAxes();
chart->axisX()->setTitleText(QString("x [m]"));
chart->axisY()->setTitleText(QString("y [m]"));
chart->setTitle("Simple chart example");
chart->resize(500,500);
// Paint the chart into an image
QImage img(500,500,QImage::Format_RGB32);
QPainter painter(&img);
QChartView *chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
chartView->show();
chartView->render(&painter);
// Set up pdf writer
QString filename = "myfile.pdf";
QPdfWriter writer(filename);
writer.setPageSize(QPagedPaintDevice::A4);
// Create the document
QTextDocument doc;
QTextCursor cursor(&doc);
cursor.insertText(QString("some text\n"));
cursor.insertImage(img);
// Print the document
doc.print(&writer);
return a.exec();
}
Although it works, I would like to avoid converting the chart into an image because it messes up the image quality. Is there a way to do it?
Here is a workaround, if the image quality is really what matters : you can use QPainter directly on the TextDocument. It requires more work and adjustement, but the quality is not lost.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Create a chart
QLineSeries *series = new QLineSeries();
series->append(0,0);
series->append(1,1);
QChart *chart = new QChart();
chart->addSeries(series);
chart->createDefaultAxes();
chart->axisX()->setTitleText(QString("x [m]"));
chart->axisY()->setTitleText(QString("y [m]"));
chart->setTitle("Simple chart example");
chart->resize(500,500);
QChartView *chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::TextAntialiasing);
chartView->show();
// Set up pdf writer
QString filename = "myfile.pdf";
QPdfWriter writer(filename);
writer.setPageSize(QPagedPaintDevice::A4);
// Create the document
QTextDocument doc;
QPainter painter(&writer);
QFont font = painter.font();
font.setPixelSize(200);
painter.setFont(font);
painter.drawText(QPoint(700,100),"Some text");
chartView->render(&painter);
doc.drawContents(&painter);
return a.exec();
}