PDA

View Full Version : Can Qwt 6.1's QwtLegendLabel give the appearance of Qwt 5.2's QwtLegendItem?



philw
19th October 2015, 23:49
We're attempting to port our use of Qwt from Qwt 5.2.3 to Qwt 6.1.2. One difficulty we're having is with conventional legend items. See this illustration:

11459

The 6.1 QwtLegendLabel isn't showing the symbol. Nor the line. Our Qwt 5.2 application code increases the horizontal width of the line with a call to QwtLegendItem::setIdentifierWidth (32) -- there doesn't seem to be an analogous method available in QwtLegendLabel. Looking at QwtLegendLabel and QwtTextLabel source code, I'm not seeing anything that would actually draw those two graphical components (line and symbol).

What am I missing? If we need to completely implement our own drawing of these legend things, what might be the best approach, in Qwt 6.1?

Thank you in advance.

Uwe
20th October 2015, 07:37
The content of the legend is provided by the items now - see QwtPlotItem::legendXYZ(). QwtPlotCurve reimplements f.e legendIcon(), providing an icon, that depends on QwtPlotCurve::LegendAttributes.

Uwe

philw
20th October 2015, 21:01
Thank you for your response, Uwe. I did try setting the QwtPlotItem's icon size arbitrarily large ... with this call in my QwtPlotItem subclass' constructor: setLegendIconSize (QSize (32, 20)) ... hoping that that would provide the Qwt 5.2 legend graphic for the item. That results in just a black rectangle of that size, as the icon for that legend label.

Is the intention that I need to DRAW that icon myself -- showing both the line color and thickness, and the symbol (see my 5.2 example in the original post) -- in a method override for the QwtGraphic QwtPlotItem::legendIcon (int index, const QSizeF& size) const virtual method? We're supposed to code that ourselves? (Not that that's inordinately difficult. It's just somewhat astonishing. So I want to make sure I'm on the right track).

Thank you again.

philw
20th October 2015, 23:13
I do now see legendIcon() virtual method provisions for QwtPlotItem. (I think we're gonna be more on our own for QwtPlotMarkers; we are conditionally showing legend items for those too). But there doesn't seem to be an elegant way to reliably (persistently) set a larger width for the legend icon, as the effect of calling QwtPlotItem::setLegendIconSize() is blown away by various API calls -- not just the calls mentioned in the comment below -- this is from our QwtPlotItem subclass' constructor:



// Set attributes uses by QwtPlotCurve::legendIcon().
setLegendAttribute (QwtPlotCurve::LegendShowLine, true);
setLegendAttribute (QwtPlotCurve::LegendShowSymbol, true);
setLegendAttribute (QwtPlotCurve::LegendShowBrush, true);

// Ensure a minimum legend icon width of 32 pixels. Note that this must
// be done after the calls to QwtPlotCurve::setLegendAttribute() because
// that method has a side-effect of re-initializing the legend icon size.

const QSize origSize = legendIconSize();
if (origSize.width() < 32)
setLegendIconSize (QSize (32, origSize.height()));

That is, I see that, subsequently calling QwtPlotCurve::setSymbol() -- which occurs asynchronously, as we have provided selection of that in our application-level plot dialog -- also blows away the icon size. This occurs internally, in a call to the local function, static void qwtUpdateLegendIconSize (QwtPlotCurve*).

I guess, this could be solved in the future with an enhancement to Qwt (QwtPlotCurve), to be able to specify a minimum legend icon width. But short of that, I think we need to keep on applying a minimum width we want each time we call a setter in the QwtPlotCurve API.

Uwe
21st October 2015, 06:32
Yes indeed there is no minimum size attribute for the legend icon. But the following code should do what you need:


virtual QwtGraphic YourCurve::legendIcon( int index, const QSizeF &size ) const
{
return QwtPlotCurve::legendIcon( index, QSizeF( qMax( size.width(), 32.0 ), size.height() ) );
}
Uwe

philw
22nd October 2015, 06:07
Uwe, thanks for all your assistance, and your great work on Qwt.

I'd like to share my re-implementation (minor simplification) of QwtPlotMarker::legendIcon(). The original 6.1.2 implementation draws a vertical piece for Markers having the "vertical line" or "cross" marker style. I felt that, just as for Curves' legend icons, a simpler linear-only horizontal rendering of the Marker's configuration ... line color and width, and symbol style and size ... would be ideal for Markers' legend icons as well.



Here's an example showing a QwtPlotMarker (having a "Cross" marker style) in the Legend. (This is with the code shown below) ...

11464


So, this is a simplification of the original implementation which we're using. Other than checking whether any line is drawn for the Marker, this implementation ignores the Marker's Style property ... compare to QwtPlotMarker::legendIcon() in src/qwt_plot_marker.cpp ...


// virtual from QwtPlotItem
QwtGraphic PlotMarker::legendIcon (int index, // (ignore, only one)
const QSizeF& iconSize) const
{
// call base class method (don't).
//-- QwtGraphic graphic = QwtPlotMarker::legendIcon (index, iconSize);
//-- return graphic;

// The following is adapted from the QwtPlotMarker::legendIcon()
// implementation (from Qwt 6.1.2). We really don't want to attempt
// to draw "vertical" components of the marker appearance, i.e. the
// vertical line, if the marker has the "VLine" or "Cross" style.
// Those nuances have been left out of this adaptation.

Q_UNUSED (index);

if (iconSize.isEmpty())
return QwtGraphic();

QwtGraphic icon;
icon.setDefaultSize (iconSize);
icon.setRenderHint (QwtGraphic::RenderPensUnscaled, true);

QPainter painter (&icon);
painter.setRenderHint (QPainter::Antialiasing,
testRenderHint(QwtPlotItem::RenderAntialiased));

const QwtPlotMarker::LineStyle markerStyle = lineStyle();
const QPen& penRef = linePen();
const QwtSymbol* symb = symbol();

if (markerStyle != QwtPlotMarker::NoLine)
{
painter.setPen (penRef);
const double y = 0.5 * iconSize.height();
QwtPainter::drawLine (&painter, 0.0, y, iconSize.width(), y);
}

if (symb)
{
const QRect rect (0.0, 0.0, iconSize.width(), iconSize.height());
symb->drawSymbol (&painter, rect);
}

return icon;
}