PDA

View Full Version : how to set long label beyond axis widget's extent?



pptux
26th August 2014, 04:32
Hi,

I need to set rotated long labels on the x axis, but the left end aligns with the y axis. The scales is compressed as below.
10578

Is there any way to make the label extend beyond the end of its axis, like this
10579

Thanks.

Uwe
26th August 2014, 09:18
What happens if you set:


plot->plotLayout()->setAlignCanvasToScale( QwtPlot::yLeft, true );Uwe

pptux
27th August 2014, 11:31
Thanks for your reply. It's not the problem of canvas alignment. After many tries, it already works. But I still don't understand;-)

I want the labels to rotate to avoid overlap when resizing. The minimum working code is below:

#include "qwt_plot.h"

class QwtPlotBarChart;
class LabelScaleDraw;

class Widget : public QWidget
{
Q_OBJECT

public:
explicit Widget(QWidget *parent = 0);

bool eventFilter(QObject *watched, QEvent *ev);

private:
void setLabels(qreal step, const QList<QwtText> &labels, LabelScaleDraw &scaleDraw);

private slots:
void setData();

private:
QwtPlot *_plot;
QwtPlotBarChart *_barChart;
LabelScaleDraw *_scaleDraw;
}; and
#include "widget.h"

#include "qwt_plot_barchart.h"
#include "qwt_plot_layout.h"
#include "qwt_scale_widget.h"

#include <QTimer>
#include <QResizeEvent>
#include <QVBoxLayout>
#include <QPushButton>
#include <QDebug>

class LabelScaleDraw: public QwtScaleDraw
{
public:
LabelScaleDraw(){}
QwtText label(double value) const
{
const int index = qRound(value);
if (index % _sampleStep == 0)
return _labelTexts.value(index);
else
return QwtText();
}
QList<QwtText> labelTexts() const
{
return _labelTexts;
}
void setLabelTexts(const QList<QwtText> &texts, int sampleStep = 1)
{
_labelTexts = texts;
_sampleStep = sampleStep > 1 ? sampleStep : 1;
invalidateCache();
}

private:
QList<QwtText> _labelTexts;
int _sampleStep = 1;
};

Widget::Widget(QWidget *parent) :
QWidget(parent)
{
_plot = new QwtPlot();
_plot->axisWidget(QwtPlot::xBottom)->installEventFilter(this);
_plot->setAutoReplot(false);
_plot->plotLayout()->setAlignCanvasToScales(true);

_scaleDraw = new LabelScaleDraw();
_plot->setAxisScaleDraw(QwtPlot::xBottom, _scaleDraw);

_barChart = new QwtPlotBarChart();
_barChart->attach(_plot);

QPushButton *button = new QPushButton("Push");

QVBoxLayout *vLayout = new QVBoxLayout();
vLayout->addWidget(_plot);
vLayout->addWidget(button);
setLayout(vLayout);

QTimer::singleShot(300, this, SLOT(setData()));
// setData();
// connect(button, &QPushButton::clicked, this, &Widget::setData);
}

bool Widget::eventFilter(QObject *watched, QEvent *ev)
{
if (watched == _plot->axisWidget(QwtPlot::xBottom) && ev->type() == QEvent::Resize)
{
QwtScaleMap xMap = _plot->canvasMap(QwtPlot::xBottom);
qreal scaleMajorInterval = xMap.transform(1) - xMap.transform(0);
setLabels(scaleMajorInterval, _scaleDraw->labelTexts(), *_scaleDraw);
_plot->replot();
}
return QWidget::eventFilter(watched, ev);
}

void Widget::setLabels(qreal step, const QList<QwtText> &labels, LabelScaleDraw &scaleDraw)
{
if (labels.isEmpty())
return;

qDebug() << "------------" << step;

qreal maxLabelWidth = 0;
for (const QwtText &text : labels)
{
QSizeF textSize = text.textSize();
if (textSize.width() > maxLabelWidth)
maxLabelWidth = textSize.width();
}

if (maxLabelWidth > step * 1.5)
{
scaleDraw.setLabelRotation(-90);
scaleDraw.setLabelAlignment(Qt::AlignLeft);
}
else if (maxLabelWidth < step * 1.5 && maxLabelWidth > step * 0.9)
{
scaleDraw.setLabelRotation(-45);
scaleDraw.setLabelAlignment(Qt::AlignLeft);
}
else
{
scaleDraw.setLabelRotation(0);
scaleDraw.setLabelAlignment(Qt::AlignHCenter);
}
scaleDraw.setLabelTexts(labels);
}

void Widget::setData()
{
const int numSamples = 10;

QVector<double> series;
QList<double> ticks;
QList<QwtText> labels;
for (int i = 0; i < numSamples; ++i)
{
series << 2 + i * 3;
ticks << i;
labels << QwtText("SteelBlue");
}
//setSample
_barChart->setSamples(series);

//setScaleDiv
QwtScaleDiv xScaleDiv(- 0.5, numSamples - 0.5);
xScaleDiv.setTicks(QwtScaleDiv::MajorTick, ticks);
_plot->setAxisScaleDiv(QwtPlot::xBottom, xScaleDiv);

//setLabels
QwtScaleMap xMap = _plot->canvasMap(QwtPlot::xBottom);
qreal scaleMajorInterval = xMap.transform(1) - xMap.transform(0);
setLabels(scaleMajorInterval, labels, *_scaleDraw);

_plot->replot();
}

What it doesn't work before is I set auto plot to true, without the explicit
_plot->replot() in the resize eventFilter; But I don't know why it wasn't work. Shouldn't it auto replot itself as the explicit one?
Thanks.