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.
Powered by vBulletin® Version 4.2.5 Copyright © 2024 vBulletin Solutions Inc. All rights reserved.