PDA

View Full Version : Axis yLeft cuts of numbers



sun
8th October 2008, 15:13
Hi,

I use a manually settable Y Axis on my custom QwtPlot.
It now sometimes occurs, that the values shown on the left arr cut at the beginning.
so 10000000 will be shown okay, because it takes the place it needs from the plot,
but 60000 or bigger (5,6,4) numbers will be cut of some pixels on the left.

Is this a Layout problem or is there something I have to do with qwt?

Thanks!
sun

Uwe
9th October 2008, 08:31
The layout engine calculates the space, that is needed for the tick labels and always gives the scales enough space for them. When your labels are cut off I guess, that the layout was not recalculated after changing the tick labels.

F.e. resizing the plot widget forces a recalculation of the layout. What happens to your labels, when you manually do this ?

Uwe

sun
9th October 2008, 09:21
Hi,

I'm not absolutely shure if I understood what you wanted me to do.
The Code that changes the yLeft axis looks as follows.



valuePlot->setYAxisScale((valuePlot->getYAxisHigh()-valuePlot->getYAxisLow())/10);
valuePlot->setAxisScale(QwtPlot::yLeft, valuePlot->getYAxisLow(), valuePlot->getYAxisHigh(), valuePlot->getYAxisScale());
valuePlot->updateLayout();

So I set the Scale of my valuePlot (inherits QwtPlot) and I believe you wanted me to call the updateLayout manually on my value Plot.
It did not help. Even a mere 6 is shown cut off.

My valuePlot was in a frame and y updated the layout of this frame. This doesn't help either!

Did I get you right?

Thanks
sun

Uwe
12th October 2008, 10:33
I'm not absolutely shure if I understood what you wanted me to do.

a) Enable a frame for your plot widget ( setFrameStyle + setLineWidth ) and check if the frame is completely visible. If not the reason for your problem is somewhere in the layout of your main window.

b) When the tick labels are cut off use your mouse and resize the main window manually. When the labels are visible after resizing we know, that a layout recalculation was missing.

Uwe

d_stranz
22nd October 2008, 17:33
I have seen this problem also. When the QwtPlot is inserted in a dialog (in my case, in a vertical layout), and there is -no- yLeft axis title, the left-most digits of long tick labels get clipped a little bit. If there is a yLeft title, this does not happen, since the title contains enough extra space to avoid clipping.

I think this is a layout problem for QwtPlot, not for our applications. When I dynamically change the axis range the labels get recalculated (and the canvas size changes if needed), but once the number of digits gets high enough (> 4 digits), the clipping starts to occur. Resizing the window does not fix the clipping problem.

David

Uwe
24th October 2008, 08:16
When the plot is resized the layout is recalculated. So the problem can't be a missing recalculation and should be somewhere inside the layout calculation. For the plot layout engine the number of digits is completely unimportant - the scale simply gets the size it needs. I've tried a couple of intervals myself and couldn't see any clipping.

Maybe the problem is in the calculation of the bounding rect for the tick label itsself - what might be platform or font dependent.

Could you change your application this way:


class YourScaleDraw: public QwtScaleDraw
{
...

virtual QwtText label(double value) const
{
QwtText tickLabel = QwtScaleDraw::label(value);
tickLabel.setBackgroundPen(Qt::red);
return tickLabel;
}
};

Assign YourScaleDraw for the left axis - now there should be a frame around all tick labels. What happens to the frame in the situation, when the labels are cut off ?

Another test you could do is to change the font. F.e. what happens, when you use a fixed font like Courier.

Uwe

d_stranz
27th October 2008, 22:08
Hi Uwe,

myPlot->setAxisScale( QwtPlot::yLeft, 0, 8000 );
myPlot->setAxisScaleDraw( QwtPlot::yLeft, new YourScaleDraw );

The red box is clipped at the left, along with a few pixels of the left-most digit.
This is on Windows. I have no way to test on other platforms.

myPlot->setAxisScale( QwtPlot::yLeft, 0, 10000 );

This also clips the box to the left of the 10000; all other boxes are OK as expected.

Regards,

David

Uwe
3rd November 2008, 11:54
Unfortunately I can't reproduce the problem. I'm afraid you need to send me code for a short application demonstrating the problem.

Uwe

Ban-chan
2nd September 2009, 20:38
I know this is an old thread but was this issue ever resolved? I have the same effect happening on my yLeft axis except for when a yAxis title is set. When I changed the font from the default (which I think is Helvetica) to Courier, this clipping no longer occurred.

Uwe
3rd September 2009, 07:58
I know this is an old thread but was this issue ever resolved?
Nobody ever sent me a demo for debugging the problem,

Uwe

d_stranz
18th September 2009, 23:35
Here you go Uwe:


#include <QtGui/QApplication>
#include <QMainWindow>
#include <qwt_plot.h>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow w;
QwtPlot * pPlot = new QwtPlot;
pPlot->setAxisScale( QwtPlot::yLeft, 0.0, 1.0e8, 5.0e6 );
w.setCentralWidget( pPlot );
w.resize( 500, 500 );
w.show();
return a.exec();
}


All of the x.5e7 labels are clipped on the left side by a couple of pixels. If the screenshot I will try to attach shows up, you can easily see this. This is Windows XP, Qt 4.5, Qwt 5.2.0, Visual C++ 2008. i have no way to test on another platform.

David

Uwe
20th September 2009, 15:46
Well, your code works fine in my environment. The main problem of this bug is, that it seems to be platform and font depending. Unfortunately the font is derived from your environment ( or depends on the font matching algo ) and not known from your code. So please do the following in your environment: assign a scale draw object to the left axis, where you return text labels with a frame. ( QwtText::setBackgroundPen() ).

When the frame is cut off it should be a problem of the layout code - if not ( what I expect ), there is a mismatch between calculating the bounding rect for the text and what is used for painting. The next step would be to strip down the code from QwtText::draw() and QwtPlainTextEngine::textSize() and QwtPlainTextEngine::textMargins() to a small demo, that paints a text to a QWidget without using Qwt.

Uwe

PS: subclassing QwtPlainTextEngine + returning left/right margins in YourPlainTextEngine::textMargins() might be a workaround for the bug.

d_stranz
21st September 2009, 03:07
Hi Uwe,

OK, a little bigger example, with a custom QwtAxisScaleDraw for the yLeft axis. As you can see from the screenshot, the left side of most of the boxes is clippped.

What next?

Regards,
David



#include <QtGui/QApplication>
#include <QMainWindow>
#include <QPainter>
#include <QPen>
#include <qwt_plot.h>
#include <qwt_scale_draw.h>
#include <qwt_text.h>
#include <qwt_painter.h>
#include <qwt_math.h>

#if QT_VERSION < 0x040000
#include <qwmatrix.h>
#define QwtMatrix QWMatrix
#else
#include <qmatrix.h>
#define QwtMatrix QMatrix
#endif

class MyScaleDraw
: public QwtScaleDraw
{
public:
MyScaleDraw() {}

protected:
virtual void drawLabel( QPainter * painter, double value ) const
{
QwtText lbl = tickLabel(painter->font(), value);
if ( lbl.isEmpty() )
return;

lbl.setBackgroundPen( QPen( Qt::black ) );
QPoint pos = labelPosition(value);

QSize labelSize = lbl.textSize(painter->font());
if ( labelSize.height() % 2 )
labelSize.setHeight(labelSize.height() + 1);

const QwtMetricsMap metricsMap = QwtPainter::metricsMap();
QwtPainter::resetMetricsMap();

labelSize = metricsMap.layoutToDevice(labelSize);
pos = metricsMap.layoutToDevice(pos);

const QwtMatrix m = labelMatrix( pos, labelSize);

painter->save();
#if QT_VERSION < 0x040000
painter->setWorldMatrix(m, true);
#else
painter->setMatrix(m, true);
#endif

lbl.draw (painter, QRect(QPoint(0, 0), labelSize) );

QwtPainter::setMetricsMap(metricsMap); // restore metrics map

painter->restore();
}

private:
};

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

QwtPlot * pPlot = new QwtPlot;
pPlot->setAxisScale( QwtPlot::yLeft, 0.0, 1.0e8, 5.0e6 );
pPlot->setAxisScaleDraw( QwtPlot::yLeft, new MyScaleDraw() );

QMainWindow w;
w.setCentralWidget( pPlot );
w.resize( 500, 500 );
w.show();
return a.exec();
}

Uwe
21st September 2009, 07:47
I tried the following code on my Linux box:


#include <QApplication>
#include <QPen>
#include <qwt_plot.h>
#include <qwt_scale_draw.h>

class MyScaleDraw: public QwtScaleDraw
{
public:
virtual QwtText label(double value) const
{
QwtText lbl = QwtScaleDraw::label(value);
lbl.setBackgroundPen(QPen(Qt::red));
return lbl;
}
};

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

QwtPlot pPlot;
pPlot.setAxisScale( QwtPlot::yLeft, 0.0, 1.0e8, 5.0e6 );
pPlot.setAxisScaleDraw( QwtPlot::yLeft, new MyScaleDraw() );

pPlot.resize( 500, 500 );
pPlot.show();

return a.exec();
}

Most of the rectangles are visible, but 2 of them are cut off too, what indicates a bug in the Qwt layout code.

So the next steps are on my side,

Uwe

d_stranz
21st September 2009, 19:45
Hi Uwe,

Thanks. And thanks for showing me an easier way to demonstrate the problem.

And by the way, this bug only occurs when the left axis title is null.

Cheers,

David

Uwe
2nd October 2009, 11:35
The layout code in QwtScaleDraw seems to be wrong by 1 pixel for the left top and right axes. On the left axis it has the effect, that the left axis is cut off by 1 pixel. At least on Linux/X11 the demo seems to be o.k. now.

Fixed in SVN ( 5.2 + trunk ),

Uwe

d_stranz
3rd October 2009, 00:26
Thanks, Uwe.

Ban-chan
9th October 2009, 22:36
Thanks Uwe, works great!