Skip to content

Commit 95457ae

Browse files
committed
fix(plot_marker): draw the legend icon symbol into a QRectF
QwtPlotMarker.legendIcon raised an AssertionError (QSize icon size) or a TypeError (QSizeF icon size) for markers with a symbol, so that such a marker could not be shown in a legend. The Qwt C++ code passes a QRect to QwtSymbol::drawSymbol, which is implicitly converted to a QRectF. The Python port passed the QRect as is, which QwtSymbol.drawSymbol rejects, and QRect(0, 0, width, height) also fails when the size is a QSizeF. - Build a QRectF, like QwtPlotCurve.legendIcon already does. - Regression tests: legend icon with QSize and QSizeF sizes, marker with a symbol shown in a QwtLegend. - Changelog entry. Refs #115 Assisted-by: Claude Opus 5.5
1 parent 3902a40 commit 95457ae

3 files changed

Lines changed: 49 additions & 2 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
- Fixed [Issue #113](https://github.com/PlotPyStack/PythonQwt/issues/113): after replacing the scale draw of an axis (`QwtPlot.setAxisScaleDraw`), the axis ticks could be misaligned with the grid lines and plot items, until the next scale division change (e.g. after panning or zooming): a replot did not fix it. The new scale draw was laid out before getting the position and length of the previous one, so that the axis reserved space for its end labels that the canvas did not take into account. The new scale draw now takes the geometry of the previous one, and the axis stays aligned with the canvas
1212
- Fixed `QwtGraphic.toPixmap(size)`, `QwtGraphic.toImage()` and `QwtGraphic.toImage(size)`, which raised a `TypeError` (possibly aborting the process, as the painter was still active on the destroyed pixmap or image) instead of rendering the graphic: they now render it like `QwtGraphic.toPixmap()` ([Issue #115](https://github.com/PlotPyStack/PythonQwt/issues/115))
13+
- Fixed `QwtPlotMarker.legendIcon` for markers with a symbol, which raised an `AssertionError` or a `TypeError`: such markers can now be shown in a legend ([Issue #115](https://github.com/PlotPyStack/PythonQwt/issues/115))
1314

1415
## Version 0.16.3
1516

‎qwt/plot_marker.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
:members:
1414
"""
1515

16-
from qtpy.QtCore import QLineF, QObject, QPointF, QRect, QRectF, QSizeF, Qt
16+
from qtpy.QtCore import QLineF, QObject, QPointF, QRectF, QSizeF, Qt
1717
from qtpy.QtGui import QPainter, QPen
1818

1919
from qwt.graphic import QwtGraphic
@@ -628,6 +628,6 @@ def legendIcon(self, index, size):
628628
x = 0.5 * size.width()
629629
painter.drawLine(QLineF(x, 0.0, x, size.height()))
630630
if self.__data.symbol:
631-
r = QRect(0, 0, size.width(), size.height())
631+
r = QRectF(0.0, 0.0, size.width(), size.height())
632632
self.__data.symbol.drawSymbol(painter, r)
633633
return icon

‎qwt/tests/test_issue115_porting_bugs.py‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from qtpy import QtGui as QG
1616
from qtpy import QtWidgets as QW
1717

18+
from qwt import QwtLegend, QwtPlot, QwtPlotItem, QwtPlotMarker, QwtSymbol
1819
from qwt.graphic import QwtGraphic
1920

2021
RED = QG.QColor(QC.Qt.red)
@@ -97,9 +98,54 @@ def test_graphic_conversion_keep_aspect_ratio(method):
9798
del app
9899

99100

101+
# ---------------------------------------------------------------------------
102+
# QwtPlotMarker.legendIcon
103+
# ---------------------------------------------------------------------------
104+
105+
106+
def _make_symbol():
107+
return QwtSymbol(
108+
QwtSymbol.Rect, QG.QBrush(RED), QG.QPen(QC.Qt.NoPen), QC.QSize(8, 8)
109+
)
110+
111+
112+
@pytest.mark.parametrize(
113+
"size", (QC.QSize(8, 8), QC.QSizeF(8.0, 8.0)), ids=("QSize", "QSizeF")
114+
)
115+
def test_marker_legend_icon_with_symbol(size):
116+
"""The legend icon of a marker with a symbol shows the symbol"""
117+
app = _ensure_app() # keep a reference alive for the duration of the test
118+
marker = QwtPlotMarker.make(xvalue=0.0, yvalue=0.0, symbol=_make_symbol())
119+
icon = marker.legendIcon(0, size)
120+
assert not icon.isNull()
121+
assert _is_red(icon.toImage(), 4, 4)
122+
del app
123+
124+
125+
def test_marker_with_symbol_in_legend():
126+
"""A marker with a symbol can be shown in a legend"""
127+
app = _ensure_app() # keep a reference alive for the duration of the test
128+
plot = QwtPlot()
129+
legend = QwtLegend()
130+
plot.insertLegend(legend)
131+
marker = QwtPlotMarker.make(
132+
xvalue=1.0, yvalue=1.0, title="Marker", symbol=_make_symbol(), plot=plot
133+
)
134+
marker.setItemAttribute(QwtPlotItem.Legend, True)
135+
plot.updateLegend(marker)
136+
label = legend.legendWidget(marker)
137+
assert label is not None
138+
assert not label.icon().isNull()
139+
plot.close()
140+
del app
141+
142+
100143
if __name__ == "__main__":
101144
for name in ("toPixmap", "toImage"):
102145
test_graphic_conversion_default_size(name)
103146
test_graphic_conversion_given_size(name)
104147
test_graphic_conversion_keep_aspect_ratio(name)
148+
for size in (QC.QSize(8, 8), QC.QSizeF(8.0, 8.0)):
149+
test_marker_legend_icon_with_symbol(size)
150+
test_marker_with_symbol_in_legend()
105151
print("OK")

0 commit comments

Comments
 (0)