PDA

View Full Version : PyQT QwtScaleDiv adds ticks to axis



mbernasocchi
16th March 2011, 11:58
Hi, i'm implementing my own QwtScaleDraw like that:

class TimeScaleDraw(QwtScaleDraw):
def __init__(self, baseTime):
QwtScaleDraw.__init__(self)
#QTime baseTime
self.baseTime = baseTime
self.setLabelAlignment(Qt.AlignLeft | Qt.AlignBottom)
self.setLabelRotation(-25.0)

def label(self, secs):
upTime = self.baseTime.addSecs(secs)
upTime = upTime.toString('dd MM yy hh:mm:ss')
return QwtText(upTime)
then I use it this way:


ticks = [0, 60, 120]
div = QwtScaleDiv()
div.setInterval(ticks[0], ticks[len(ticks)-1])
div.setTicks(QwtScaleDiv.MinorTick, [])
div.setTicks(QwtScaleDiv.MediumTick, [])
div.setTicks(QwtScaleDiv.MajorTick, ticks)
draw = TimeScaleDraw(QDateTime(self.main.timeMin))
draw.setScaleDiv(div)
self.plot.setAxisScaleDraw(QwtPlot.xBottom, draw)
self.plot.setAxisScale(QwtPlot.yLeft, self.main.valueMin, self.main.valueMax)
I'd like to have only 3 ticks (where there actually are values) on my x axis, but some how I get more ticks added (see screen shot). what do i do wrong? any suggestion?

Uwe
16th March 2011, 18:45
Use QwtPlot::setAxisScaleDiv() - the ticks directly assigned to your scaleDraw object will be overwritten by the next replot.

Uwe

mbernasocchi
17th March 2011, 10:11
Hi Uwe, thanks for the reply, I had tryed it already and the result was worse, but I tryed it again just to be shure. it does not work (see attach).
my code is:


ticks = [0, 60, 120]
div = QwtScaleDiv()
div.setInterval(ticks[0], ticks[len(ticks)-1])
div.setTicks(QwtScaleDiv.MinorTick, [])
div.setTicks(QwtScaleDiv.MediumTick, [])
div.setTicks(QwtScaleDiv.MajorTick, ticks)
draw = TimeScaleDraw(QDateTime(self.main.timeMin))
#draw.setScaleDiv(div)
self.plot.setAxisScaleDiv(QwtPlot.xBottom, div)
self.plot.setAxisScaleDraw(QwtPlot.xBottom, draw)
self.plot.setAxisScale(QwtPlot.yLeft, self.main.valueMin, self.main.valueMax)

corrado1972
29th March 2011, 13:05
Hi, did you solved ?
bye

mbernasocchi
29th March 2011, 17:08
no :( any ideas?

Uwe
29th March 2011, 18:48
What type of answer do you expect for "it does not work" ?

Uwe

mbernasocchi
7th April 2011, 22:50
Hi Uwe, well the situation for me is that I've the following code:


ticks = [0, 60, 120]
div = QwtScaleDiv()
div.setInterval(ticks[0], ticks[len(ticks)-1])
div.setTicks(QwtScaleDiv.MinorTick, [])
div.setTicks(QwtScaleDiv.MediumTick, [])
div.setTicks(QwtScaleDiv.MajorTick, ticks)
draw = TimeScaleDraw(QDateTime(self.main.timeMin))
#draw.setScaleDiv(div)
self.plot.setAxisScaleDiv(QwtPlot.xBottom, div)
self.plot.setAxisScaleDraw(QwtPlot.xBottom, draw)
self.plot.setAxisScale(QwtPlot.yLeft, self.main.valueMin, self.main.valueMax)
which instead of generating only 3 major ticks at the desired location it creates many more ticks as shown in the attachement in the post above. you can see the full code at http://hub.qgis.org/projects/multiview/repository/revisions/master/changes/visualizations/timeplotwidget.py i'd be super if you could give me an hint...
thanks a lot
Marco

Uwe
11th April 2011, 07:09
QwtScaleDiv internally has a flag, that indicates if it is valid or not - if not it gets recalculated from the autoscaler. Of course this is a bad class design and has to do with the history of the QwtScaleDiv class.

Instead you have to initialize your QwtScaleDiv object this way ( C++ ):


QList<double> ticks[QwtScaleDiv::NTickTypes];
ticks[QwtScaleDiv::MajorTick] << 0.0 << 60.0 << 120.0;

QwtScaleDiv scaleDiv(
ticks[QwtScaleDiv::MajorTick].first(),
ticks[QwtScaleDiv::MajorTick].last(),
ticks );

setAxisScaleDiv(QwtPlot::xBottom, scaleDiv);

Uwe

mbernasocchi
11th April 2011, 12:31
Hi Uwe, thanks for the answer, I tried and it almost works, now I just dont' have the labels anymore (the ticks are at the right place). (see screenshot and note that the picker shows the correct value)
the code I use is:


#update axes
div = QwtScaleDiv(ticks[0], ticks[len(ticks)-1], ticks, [],[])
baseTime = QDateTime(self.mainWidget.timeMin)
draw = TimeScaleDraw(baseTime)
self.plot.setAxisScaleDraw(QwtPlot.xBottom, draw)
self.plot.setAxisScaleDiv(QwtPlot.xBottom, div)

class TimeScaleDraw(QwtScaleDraw):
def __init__(self, baseTime):
QwtScaleDraw.__init__(self)
#QTime baseTime
self.baseTime = baseTime
self.setLabelAlignment(Qt.AlignLeft | Qt.AlignBottom)
self.setLabelRotation(-25.0)

def label(self, secs):
upTime = self.baseTime.addSecs(secs)
upTime = upTime.toString('dd MM yy hh:mm:ss')
return QwtText(upTime)


as well, using python one has to know this: http://pyqwt.sourceforge.net/doc5/reference.html#PyQt4.Qwt5.QwtScaleDiv
do you have an idea why this happens?
6221
thanks Marco

Uwe
13th April 2011, 08:37
Is your overloaded label method called - and if yes with which values ?

Uwe

mbernasocchi
13th April 2011, 10:12
Hi uwe, spot on... no it si not called, when I dont use the
self.plot.setAxisScaleDiv(QwtPlot.xBottom, div) line then it gets called automatically with the correct values. Do I need to call it myself? where?
ciao Marco

Added after 40 minutes:

Uwe, btw, it is not only my overloaded label that doesn't get called, if I remove the label method in my QwtScaleDraw, nothing changes, the labels are not drawn. :(

Uwe
13th April 2011, 10:59
labels are painted for major ticks only. I'm not familiar with the Python API, but maybe the ticks you have set are the minor or medium ticks ?

Uwe

mbernasocchi
13th April 2011, 11:29
Uwe thanks a lot... you do indeeed know your "baby" by heart. i think there is a bug in the python API documentation. by changing:

div = QwtScaleDiv(ticks[0], ticks[len(ticks)-1], [], [], ticks)
to

div = QwtScaleDiv(ticks[0], ticks[len(ticks)-1], ticks, [], [])

it all works although the documentation it says:
scaleDiv = QwtScaleDiv(
lower, upper, majorTicks, mediumTicks, minorTicks)
I'll contact the API author. thanks a lot Again
ciao Marco
6229