PDA

View Full Version : setting ticks on QwtPlotScaleItem



ericLemanissier
8th August 2014, 18:26
Hello,

Firstly, thank you very much for Qwt, it is such a great tool !

I am currently trying to implement a plot with the standard axisWidgets (left and bottom) having automatic ticks outside of the plot, and i need to have also one vertical scale and one horizontal scale inside the plot. For this I attached 2 QwtPlotScaleItem instances to the plot. I need to have the ticks at specific positions for these 2 scales, so I call QwtPlotScaleItem::setScaleDiv.The problem is when the plot is zoomed:the ticks coordinates do not seem to be updated, so it is not coherent any more with the graph and the axis widgets.
What am I doing wrong ?

before zooming:
10548
after zooming:
10547

Thanks again

Eric

Uwe
9th August 2014, 10:52
Using QwtPlotScaleItem::setScaleDiv sets up an individual scale that is unrelated to the coordinate system spanned by the outer axes - what is probably not what you want to do.

So I guess you are looking for something like the following code:


class ScaleItem: public QwtPlotScaleItem
{
public:
ScaleItem():
QwtPlotScaleItem( QwtScaleDraw::LeftScale)
{
}

protected:
void updateScaleDiv( const QwtScaleDiv& xScaleDiv,
const QwtScaleDiv& yScaleDiv )
{
QwtScaleDiv sd( yScaleDiv.lowerBound(), yScaleDiv.upperBound() );
sd.setTicks( QwtScaleDiv::MajorTick, QList<double>() << 1 << 2 << ... );

QwtPlotScaleItem::updateScaleDiv( xScaleDiv, sd );
}
};Uwe

ericLemanissier
13th August 2014, 12:05
Thank you for your answer.

I made a solution just a bit more generic, which works well:


class ScaleItem: public QwtPlotScaleItem
{
public:
ScaleItem(const QwtScaleDiv& scaleDiv, QwtScaleDraw::Alignment alignment = QwtScaleDraw::BottomScale,
const double pos = 0.0 ):
QwtPlotScaleItem( alignment, pos), m_scaleDiv(scaleDiv), m_alignment(alignment)
{
}

protected:
void updateScaleDiv( const QwtScaleDiv& xScaleDiv,
const QwtScaleDiv& yScaleDiv )
{
switch(m_alignment)
{
case QwtScaleDraw::BottomScale:
case QwtScaleDraw::TopScale:
m_scaleDiv.setInterval(xScaleDiv.interval());
QwtPlotScaleItem::updateScaleDiv( m_scaleDiv, yScaleDiv );
break;
case QwtScaleDraw::LeftScale:
case QwtScaleDraw::RightScale:
m_scaleDiv.setInterval(yScaleDiv.interval());
QwtPlotScaleItem::updateScaleDiv( xScaleDiv, m_scaleDiv);
break;
}

}
private:
QwtScaleDiv m_scaleDiv;
const QwtScaleDraw::Alignment m_alignment;
};

It gives the following expected result after zooming:
10553

I know have a question about the labels of these scale. As you can see in the screenshot above, they are hardly reading because the overlap with the colored square. I am using QwtPlotScaleItem::scaleDraw()->setLabelAlignment(Qt::AlignBottom | Qt::AlignLeft); which improves the situation.
However i need to shift a bit the labels (on the left for the horizontal scale, and to the bottom for the vertical scale). I tried the QwtPlotScaleItem::scaleDraw()->setSpacing(40) but it does not shift in the direction I need. Do i need to subclass QwtScaleDraw for this ?

Again, many thanks !

Eric

Uwe
14th August 2014, 09:24
Maybe setting a different alignment ( f.e labels left from the ticks for horizontal scales ) is what you need.

Unfortunately the methods for calculating the geometry of the labels are not virtual and can't be manipulated easily.

Uwe

ericLemanissier
14th August 2014, 14:20
What do you mean by different alignment ? I already tried QwtScaleDraw::setLabelAlignment(Qt::AlignLeft), and it does not allow to increase the shift between the label and the tick (the horizontal shift in this case).

I found an interesting other way to handle this : I could subclass QwtTextEngine and override QwtTextEngine::textMargins( const QFont &font, const QString &text, double &left, double &right, double &top, double &bottom ), and then calling QwtText::setTextEngine to force the use of this textengine for PlainText. However this method is static, so it will also set the textEngine for all other QwtText, an it is not possible since I have other plots displayed at the same time which need to keep the standard behavior for their QwtText.
Do you think there could be a possibility in this direction ?

Eric

Uwe
15th August 2014, 09:50
You could overload QwtScaleDraw::label() and simply add a blank at the end of each text.

If you want to continue with a modified text engine you could register it with a new format type ( QwtText::setTextEngine() ) and return the labels of QwtScaleDraw::label() using this specific format type.

Uwe