QCustomPlot Discussion and Comments

Consistent placing of text in a QCPItemTextReturn to overview

I have files of data from an electronic instrument that I need to plot, and then be able to insert the plots in high quality into reports in a word processor. I'm using QCustomPlot to produce a graph in a promoted widget, then inserting the graph into a QTextEdit, and finally rendering the graph into an SVG file using QSvgGenerator. The vector nature of the data is preserved the whole way, and the SVG file can be inserted into the word processor document with the required high quality.

All bar one of the elements of the graph seem to be working fine. However, I'm having trouble with some text in a QCPItemText. I'm aiming to locate this close to the top of the plot, with its centre aligned to be above the centre of the x-axis. In the widget, this seems to be the case, but in the QTextEdit the rest of the plot has shrunk slightly, while the QCPItemText has not, resulting in it being a little to the right of where I want it. (Both the widget and the QTextEdit are set graphically in the form mainwindow.ui to be 471 x 271). Even though the effect is relatively small, why do the QCPItemText and the rest of the graph appear to scale differently?

In both the above cases, the rectangle around the text is close in to the text. However, in the SVG file, the rectangle is extended to the right of the text, typically by about a quarter of the length of the text itself. The appearance is quite different from how it is in the widget and the QCPItemText: neither the text nor the rectangle around the text is centred above the centre of the x-axis.

Here's my code:

QCPDocumentObject *plotObjectHandler = new QCPDocumentObject(this);
    ui->textEdit->document()->documentLayout()->registerHandler(QCPDocumentObject::PlotTextFormat, plotObjectHandler);

    int width = 450;
    int height = 250;

    QSvgGenerator generator;
    generator.setFileName(QCoreApplication::applicationDirPath() + "/test.svg");
    generator.setSize(QSize(width, height));
    generator.setViewBox(QRect(2, 2, width-2, height-2));  // come in from the edge to avoid a border that is added somewhere...
    generator.setTitle("SVG Generator Graph");
    generator.setDescription("A test SVG drawing of a QCustomPlot");

    ui->plot->addGraph();
    ui->plot->replot();
    ui->plot->plotLayout()->insertRow(0);  //Make space for a title/caption (QCPItemText)
    ui->plot->plotLayout()->setRowStretchFactor(0, 0.1);    //set height of the new row
    ui->plot->xAxis->setRange(0, 10);
    ui->plot->yAxis->setRange(0, 12);
    ui->plot->xAxis->setLabel("X-axis label");
    ui->plot->yAxis->setLabel("Y-axis label");

    ui->plot->replot(); //need to do this before getting the coordinates of the axisRect

    int left = ui->plot->axisRect()->left();
    int right = ui->plot->axisRect()->right();

    QCPItemText *caption = new QCPItemText(ui->plot);
    caption->setPen(Qt::SolidLine);  // draw the box round the text
    caption->setFont(QFont("Sans", 12, QFont::Bold));
    caption->setText("ABLE WAS I ERE I SAW ELBA");
    caption->setTextAlignment(Qt::AlignCenter);    //centre text within its rectangle
    caption->setPositionAlignment(Qt::AlignHCenter | Qt::AlignTop);    // use the centre top of the rectangle to position it
    caption->position->setType(QCPItemPosition::ptAbsolute);
    caption->position->setCoords((left+right)/2, 5);
    caption->setClipToAxisRect(false);

    ui->plot->replot();

    QTextCursor cursor = ui->textEdit->textCursor();
    cursor.insertText(QString(QChar::ObjectReplacementCharacter), QCPDocumentObject::generatePlotFormat(ui->plot, width, height));

    QPainter painter;
    painter.begin(&generator);
    ui->textEdit->render(&painter);
    painter.end();

Am I doing something wrong? Is it a problem with my code, with QCustomPlot or with QSvgGenerator? Any help will be gratefully received!

Best wishes and thanks,

Peter

Hi Peter,

From a quick look, I'd suspect that your absolute positioning is the issue here:

    caption->position->setType(QCPItemPosition::ptAbsolute);
    caption->position->setCoords((left+right)/2, 5);

This makes your text item have a fixed position relative to the top left of the QCustomPlot viewport, irrespective of any size changes of the axis rect or the viewport width/height.

I recommend doing this instead:

    caption->position->setType(QCPItemPosition::ptAxisRectRatio);
    caption->position->setCoords(0.5, 0.02);

This way your text is always centered horizontally in the axis rect (coordinate 0.5 in axis rect ratio coordinates), and 2% from the top edge.

Does this fix your issue?

DerManu,

Many thanks for this. I can see that your code is a much better approach. I have tweaked it slightly in order to put the caption above the graph rather than in the AxisRect:

caption->position->setCoords(0.5, -0.2);

but unfortunately there remains a problem. The textEdit now displays what I want (see https://www.dropbox.com/s/tu29bbykqunhoys/Screenshot_of_textEdit.png?dl=0), but in the SVG file that it goes on to create, while the text rectangle ends are in the same position relative to the horizontal axis (i.e. at about 1.5 and 8.5), the text now does not fill the rectangle, and is justified to the left (see https://www.dropbox.com/s/64l47zg0vozbz9t/test.svg?dl=0).

The question in my mind is whether this remaining problem is due to QCustomPlot or to rendering the textEdit with QSvgGenerator. Any guidance on this will be greatly appreciated!

Peter