LegendItem: fix docs & minor bugs (#1437)

* LegendItem: fix spelling mistake

* LegendItem: remove unused curRow variable

* LegendItem: correct calculation of rowCount

Previously, rowCount would never be updated unless setColumnCount()
was called. This fixes that issue.
It also fixes that setColumnCount() rounded down (floored) the
number of rows, instead of providing an accurate number:
e.g. 4 items in 3 columns would yield rowCount=1, when it should be 2

* LegendItem: remove rowCount argument (not implemented)

Logic to actually use the rowCount argument was not implemented.
Users might expect rowCount to limit the number of rows to e.g. 1,
but that is not what the current code does (it only works with limiting
the number of columns).
Thus, we were exposing an unused/misleading parameter to users.

This can and should be reverted if the logic for limiting the number
of rows is added.

* LegendItem: add colCount docs

* test (LegendItem): remove unused curRow variable

* test (LegendItem): check increasing rowCount as add items

* Fixed logic in placement of items in legend with multiple columns

* Actual row count here should be 2, not 3

Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
This commit is contained in:
Drew 2021-02-06 02:00:34 -05:00 committed by GitHub
parent bac2ff5b4b
commit e7ceebd867
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 32 additions and 18 deletions

View File

@ -13,7 +13,7 @@ win = pg.plot()
win.setWindowTitle('pyqtgraph example: BarGraphItem') win.setWindowTitle('pyqtgraph example: BarGraphItem')
# # option1: only for .plot(), following c1,c2 for example----------------------- # # option1: only for .plot(), following c1,c2 for example-----------------------
# win.addLegend(frame=False, rowCount=1, colCount=2) # win.addLegend(frame=False, colCount=2)
# bar graph # bar graph
x = np.arange(10) x = np.arange(10)

View File

@ -1,4 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import math
from .GraphicsWidget import GraphicsWidget from .GraphicsWidget import GraphicsWidget
from .LabelItem import LabelItem from .LabelItem import LabelItem
from ..Qt import QtGui, QtCore from ..Qt import QtGui, QtCore
@ -30,8 +32,7 @@ class LegendItem(GraphicsWidget, GraphicsWidgetAnchor):
def __init__(self, size=None, offset=None, horSpacing=25, verSpacing=0, def __init__(self, size=None, offset=None, horSpacing=25, verSpacing=0,
pen=None, brush=None, labelTextColor=None, frame=True, pen=None, brush=None, labelTextColor=None, frame=True,
labelTextSize='9pt', rowCount=1, colCount=1, labelTextSize='9pt', colCount=1, sampleType=None, **kwargs):
sampleType=None, **kwargs):
""" """
============== =============================================================== ============== ===============================================================
**Arguments:** **Arguments:**
@ -54,6 +55,10 @@ class LegendItem(GraphicsWidget, GraphicsWidgetAnchor):
accepted by :func:`mkPen <pyqtgraph.mkPen>` is allowed. accepted by :func:`mkPen <pyqtgraph.mkPen>` is allowed.
labelTextSize Size to use when drawing legend text. Accepts CSS style labelTextSize Size to use when drawing legend text. Accepts CSS style
string arguments, e.g. '9pt'. string arguments, e.g. '9pt'.
colCount Specifies the integer number of columns that the legend should
be divided into. The number of rows will be calculated
based on this argument. This is useful for plots with many
curves displayed simultaneously. Default: 1 column.
sampleType Customizes the item sample class of the `LegendItem`. sampleType Customizes the item sample class of the `LegendItem`.
============== =============================================================== ============== ===============================================================
@ -71,8 +76,7 @@ class LegendItem(GraphicsWidget, GraphicsWidgetAnchor):
self.offset = offset self.offset = offset
self.frame = frame self.frame = frame
self.columnCount = colCount self.columnCount = colCount
self.rowCount = rowCount self.rowCount = 1
self.curRow = 0
if size is not None: if size is not None:
self.setGeometry(QtCore.QRectF(0, 0, self.size[0], self.size[1])) self.setGeometry(QtCore.QRectF(0, 0, self.size[0], self.size[1]))
@ -231,29 +235,37 @@ class LegendItem(GraphicsWidget, GraphicsWidgetAnchor):
# FIND RIGHT COLUMN # FIND RIGHT COLUMN
if not self.layout.itemAt(row, col): if not self.layout.itemAt(row, col):
break break
if col + 2 == nCol: else:
# MAKE NEW ROW if col + 2 == nCol:
col = 0 # MAKE NEW ROW
row += 1 col = 0
row += 1
self.layout.addItem(sample, row, col) self.layout.addItem(sample, row, col)
self.layout.addItem(label, row, col + 1) self.layout.addItem(label, row, col + 1)
# Keep rowCount in sync with the number of rows if items are added
self.rowCount = max(self.rowCount, row + 1)
print(f"_addItemToLayout set self.rowCount = {self.rowCount} \t row = {row} \t col = {col}")
def setColumnCount(self, columnCount): def setColumnCount(self, columnCount):
"""change the orientation of all items of the legend """change the orientation of all items of the legend
""" """
if columnCount != self.columnCount: if columnCount != self.columnCount:
self.columnCount = columnCount self.columnCount = columnCount
self.rowCount = int(len(self.items) / columnCount)
self.rowCount = math.ceil(len(self.items) / columnCount)
print(f"setColumnCount set self.rowCount = {self.rowCount}")
for i in range(self.layout.count() - 1, -1, -1): for i in range(self.layout.count() - 1, -1, -1):
self.layout.removeAt(i) # clear layout self.layout.removeAt(i) # clear layout
for sample, label in self.items: for sample, label in self.items:
self._addItemToLayout(sample, label) self._addItemToLayout(sample, label)
self.updateSize() self.updateSize()
print(f"end result is self.rowCount = {self.rowCount}")
print("\n")
def getLabel(self, plotItem): def getLabel(self, plotItem):
"""Return the labelItem inside the legend for a given plotItem """Return the labelItem inside the legend for a given plotItem
The label-text can be changed via labenItem.setText The label-text can be changed via labelItem.setText
""" """
out = [(it, lab) for it, lab in self.items if it.item == plotItem] out = [(it, lab) for it, lab in self.items if it.item == plotItem]
try: try:
@ -297,13 +309,13 @@ class LegendItem(GraphicsWidget, GraphicsWidgetAnchor):
width = 0 width = 0
for row in range(self.layout.rowCount()): for row in range(self.layout.rowCount()):
row_height = 0 row_height = 0
col_witdh = 0 col_width = 0
for col in range(self.layout.columnCount()): for col in range(self.layout.columnCount()):
item = self.layout.itemAt(row, col) item = self.layout.itemAt(row, col)
if item: if item:
col_witdh += item.width() + 3 col_width += item.width() + 3
row_height = max(row_height, item.height()) row_height = max(row_height, item.height())
width = max(width, col_witdh) width = max(width, col_width)
height += row_height height += row_height
self.setGeometry(0, 0, width, height) self.setGeometry(0, 0, width, height)
return return

View File

@ -13,7 +13,6 @@ def test_legend_item_basics():
assert legend.columnCount == 1 assert legend.columnCount == 1
assert legend.rowCount == 1 assert legend.rowCount == 1
assert legend.curRow == 0
assert legend.labelTextColor() is None assert legend.labelTextColor() is None
assert legend.labelTextSize() == '9pt' assert legend.labelTextSize() == '9pt'
@ -65,21 +64,24 @@ def test_legend_item_basics():
legend.addItem(scatter, name="Scatter") legend.addItem(scatter, name="Scatter")
assert len(legend.items) == 2 assert len(legend.items) == 2
assert legend.columnCount == 1 assert legend.columnCount == 1
assert legend.rowCount == 1 assert legend.rowCount == 2
curve = pg.PlotDataItem(name="Curve") curve = pg.PlotDataItem(name="Curve")
legend.addItem(curve, name="Curve") legend.addItem(curve, name="Curve")
assert len(legend.items) == 3 assert len(legend.items) == 3
assert legend.rowCount == 3
scrabble = pg.PlotDataItem(name="Scrabble") scrabble = pg.PlotDataItem(name="Scrabble")
legend.addItem(scrabble, name="Scrabble") legend.addItem(scrabble, name="Scrabble")
assert len(legend.items) == 4 assert len(legend.items) == 4
assert legend.layout.rowCount() == 4 assert legend.layout.rowCount() == 4
assert legend.rowCount == 4
legend.setColumnCount(2) legend.setColumnCount(2)
assert legend.columnCount == 2
assert legend.rowCount == 2 assert legend.rowCount == 2
assert legend.layout.rowCount() == 3 assert legend.layout.rowCount() == 2
# Remove items # Remove items
# ---------------------------------------------------- # ----------------------------------------------------
@ -91,7 +93,7 @@ def test_legend_item_basics():
assert len(legend.items) == 3 assert len(legend.items) == 3
legend.removeItem(curve) legend.removeItem(curve)
assert legend.rowCount == 2 assert legend.rowCount == 2 # rowCount will never decrease when removing
assert legend.layout.rowCount() == 1 assert legend.layout.rowCount() == 1
assert curve not in legend.items assert curve not in legend.items
assert len(legend.items) == 2 assert len(legend.items) == 2