legend documentation

662 views
Skip to first unread message

Jaime Heiss

unread,
Apr 20, 2019, 3:25:53 PM4/20/19
to pyqtgraph
Hello.
Is there any updated documentation about legend handling?
I need to remove the box, change background color and make thicker lines as well as horizontal lines instead of the diagonals. If anybody could post an example, I will appreciate it.

Thanks.

Patrick

unread,
Apr 22, 2019, 11:13:09 PM4/22/19
to pyqtgraph
Hi,

I think the answer to your question is "no" unfortunately, but the following does what you want. It isn't pretty though, so don't judge me! It's a modification of the LegendItem demo, implementing a custom ItemSample subclass to modify the legend marker.

import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui

# A custom ItemSample to draw in legend
from pyqtgraph.graphicsItems.LegendItem import ItemSample
from pyqtgraph.graphicsItems.ScatterPlotItem import drawSymbol
class MyItemSample(ItemSample):
   
def __init__(self, item):
       
super().__init__(item)

   
def paint(self, p, *args):
        opts
= self.item.opts

       
if opts.get('fillLevel',None) is not None and opts.get('fillBrush',None) is not None:
            p
.setBrush(pg.mkBrush(opts['fillBrush']))
            p
.setPen(pg.mkPen(None))
            p
.drawPolygon(QtGui.QPolygonF([QtCore.QPointF(2,10), QtCore.QPointF(18,10), QtCore.QPointF(18,18), QtCore.QPointF(2,18)]))

       
if not isinstance(self.item, pg.ScatterPlotItem):
            p
.setPen(pg.mkPen(opts['pen']))
            p
.drawLine(2, 10, 18, 10)

        symbol
= opts.get('symbol', None)
       
if symbol is not None:
           
if isinstance(self.item, pg.PlotDataItem):
                opts
= self.item.scatter.opts

            pen
= pg.mkPen(opts['pen'])
            brush
= pg.mkBrush(opts['brush'])
            size
= opts['size']

            p
.translate(10,10)
            path
= drawSymbol(p, symbol, size, pen, brush)

plt
= pg.plot()
plt
.setWindowTitle('pyqtgraph example: Legend')
#legend = plt.addLegend() # Don't use this, instead create and populate legend manually
l
= pg.LegendItem((100,60), offset=(70,30))  # args are (size, offset)
l
.setParentItem(plt.graphicsItem())   # Note we do NOT call plt.addItem in this case

# Crude patch of the legend paint() method
import types
def paint(self, p, *args):
    p
.fillRect(self.boundingRect(), pg.mkBrush(192,0,0,50))
l
.paint = types.MethodType(paint, l)

# Fix the spacing between legend symbol and text.
# This is probably needs to be added to the __init__() of LegendItem...
l
.layout.setHorizontalSpacing(20)

c1
= plt.plot([1,3,2,4], pen='r', symbol='o', symbolPen='r', symbolBrush=0.5, name='red plot')
c2
= plt.plot([2,1,4,3], pen='g', fillLevel=0, fillBrush=(255,255,255,30), name='green plot')

l
.addItem(MyItemSample(c1), "my red plot")
l
.addItem(MyItemSample(c2), "my green plot")

## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
   
import sys
   
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
       
QtGui.QApplication.instance().exec_()


You might instead want to subclass LegendItem instead of just patching the paint() method like that, and you could modify the addItem() method to use your custom ItemSample by default.

Patrick

Jaime Heiss

unread,
Apr 23, 2019, 7:52:58 PM4/23/19
to pyqtgraph
Thank you so much Patrick.
This is almost perfect!
I just have one stupid question:
How do I clear the legend every time I clear the plot?

Thanks!

Patrick

unread,
Apr 23, 2019, 11:37:18 PM4/23/19
to pyqtgraph
Hi,

Glad it is of some use to you! Items can be removed from the legend in two ways:
# Remove by label
l
.removeItem("my red plot")
# Remove by reference to plot item
l
.removeItem(c2)


There isn't a l.clear() method or similar, which would be nice, but keeping with the theme of this thread, here's a hacky one-liner to do that:
# Remove all items
[ l.removeItem(sample.item) for sample, label in list(l.items) ]

Patrick

Jaime Heiss

unread,
Apr 25, 2019, 6:13:28 PM4/25/19
to pyqtgraph
Awesome!


On Saturday, April 20, 2019 at 12:25:53 PM UTC-7, Jaime Heiss wrote:

jona.j...@gmail.com

unread,
Apr 26, 2019, 4:59:12 AM4/26/19
to pyqtgraph
Patrick mentioned "You might instead want to subclass LegendItem instead of just patching the paint() method like that".
I have an example here doing just that:


It make the background of the Legend white and doubles the size of the legend item lines.

Best regards,
Jona

Jaime Heiss

unread,
May 10, 2019, 7:54:29 PM5/10/19
to pyqtgraph
Hi again.
Actually I'm not being able to delete the legend. It works fine as long as I don't add additional legends. If the number of legends increase, they stay there forever.

I have a qt designer GUI and  when I add more signals to be plotted, I get a large legend box that never shrinks back.
I'm rather new to this whole PyQt thing, so sorry if I am making obvious mistakes.
Since the plotting routine is been called very frequently, I defined the L object in the init as self.l=[]
Then, within my updateplot(self) method I have the following:

self.l = pg.LegendItem((100, 60), offset=(70, 30))  # args are (size, offset)
self.l.setParentItem(plotCanv.graphicsItem()) # Note we do NOT call plt.addItem in this case
# Crude patch of the legend paint() method
self.l.paint = types.MethodType(paint, self.l)

# Fix the spacing between legend symbol and text.
# This is probably needs to be added to the __init__() of LegendItem...
self.l.layout.setHorizontalSpacing(20)

and then for plotting on my plotCanv graphicsView I do
plotCanv.plot(s[2][p0:pf],s[3][p0:pf],
pen=(i,len(self.sig2p)),connect="finite")

and add the respective legend, which I try to store in self.addedplots list so I can delete it latter.

c1 = plotCanv.plot([1,3,2,4], pen=(i,len(self.sig2p)),
fillLevel=100, fillBrush=(255,255,255),name=s[4])
self.l.addItem(MyItemSample(c1), s[4])
self.addedplots.append(c1)



So, before doing any of this plotting I am trying to delete the previous stuff with this:
plotCanv.clear()
for sample in self.addedplots:
self.l.removeItem(sample)

But it's not working as prior legends just stay there, allthough the previous plot gets deleted.
What I need (if I can't just remove the legends) is to completely wipe out or restart the whole graphicsview widget.

Any advice will be appreciated.

Thanks!

Patrick

unread,
May 11, 2019, 2:35:08 AM5/11/19
to pyqtgraph
Hi,

Hi,

You can remove the legend(s) altogether with something like:
# Remove legends in your list
for l in self.l:
    plt
.scene().removeItem(l)
   
self.l.removeItem(l)

# or indiscriminately remove anything that looks like a legend...
 
for item in plt.childItems():
   
if isinstance(item, pg.LegendItem):
        plt
.scene().removeItem(item)

Also, I can see another problem you may have. If you are keeping a list of legend items (with self.l = [] and self.l.addItem(MyItemSample(c1), s[4]) etc.), but are then are doing self.l = pg.LegendItem((100, 60), offset=(70, 30)), then you're clobbering your list. Any items inside the list and added to the scene will still exist, but you've lost the references to them, so you won't be able to remove them. Try something like
l = pg.LegendItem((100, 60), offset=(70, 30))

l
.setParentItem(plotCanv.graphicsItem())
# ...
self.l.append(l)

Patrick

Jaime Heiss

unread,
May 16, 2019, 4:32:32 PM5/16/19
to pyqtgraph
Thanks Patrick.
Actually your answer:
"# or indiscriminately remove anything that looks like a legend...
 
for item in plt.childItems():
    
if isinstance(item, pg.LegendItem):
        plt
.scene().removeItem(item)
"
Solved all my issues, so I don't need the self.l stuff.

Thanks again.

Cheers!
Reply all
Reply to author
Forward
0 new messages