Update TextItem

66 views
Skip to first unread message

Greydon Gilmore

unread,
Jan 16, 2019, 2:56:27 PM1/16/19
to pyqtgraph
Hello,

I am using pg.LinearRegionItem to select an area on the plot. 
Once I have selected the area I have set up a mouse event, that when left button is clicked the region borders will be displayed using pg.TextItem. 

However, I want to be able to replace the pg.TextItem is the LinearRegionItem is changed and a new mouse click is detected

win = pg.GraphicsWindow()
pl = win.addPlot(row=1, col=0)
pl.plot(my_data)
lr = pg.LinearRegionItem(orientation=pg.LinearRegionItem.Horizontal)
pl.addItem(lr)

def on_click(ev):
    if (ev.button() == QtCore.Qt.LeftButton):
    lo,hi = lr.getRegion()
    print (lo,hi)
    ti = pg.TextItem('', anchor=(0,1.1), color=(146, 146, 146), fill='w')
    pl.addItem(ti)
    ti.setText(str(round(lo,3))+ ' ' + str(round(hi,3)))
    ev.accept()

pl.vb.mouseClickEvent = on_click

Any help would be appreciated!

Greydon

Patrick

unread,
Jan 16, 2019, 10:57:18 PM1/16/19
to pyqtgraph
Hi,

I think what you are asking is you'd like the label text to always remain inside the region, rather than being at a fixed point. So use the SetPos method (it's inherited from QGraphicsItem) to move it on update.

Also, here's an example with couple of other ideas: why not update the label whenever the region is changed? 

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
import numpy as np
import pyqtgraph as pg
from pyqtgraph.graphicsItems.InfiniteLine import InfLineLabel

app
= QtWidgets.QApplication(sys.argv)

my_data
= np.random.random(10)


win
= pg.GraphicsWindow()
pl
= win.addPlot(row=1, col=0)
pl
.plot(my_data)

ti
= pg.TextItem('', anchor=(0,1.1), color=(146, 146, 146), fill='w')
pl
.addItem(ti)

lr
= pg.LinearRegionItem(orientation=pg.LinearRegionItem.Horizontal)
pl
.addItem(lr)

# Here's another idea:
# Add the value label functionality to the InfiniteLine components of the LinearRegionItem
lr
.lines[0].label = InfLineLabel(lr.lines[0], text="{value:0.3f}")
lr
.lines[1].label = InfLineLabel(lr.lines[1], text="{value:0.3f}")

def update_regiontext():
    lo
,hi = lr.getRegion()
    ti
.setText("{:0.3f} {:0.3f}".format(lo, hi))
    ti
.setPos(0, lo)

update_regiontext
()

# If you really want to only update on click then uncomment code below
# def on_click(ev):
#     if (ev.button() == QtCore.Qt.LeftButton):
#         update_regiontext()
#         ev.accept()
# pl.vb.mouseClickEvent = on_click

# Otherwise, this will update whenever the region is changed
lr
.sigRegionChanged.connect(update_regiontext)

win
.show()
sys
.exit(app.exec_())


Patrick

Greydon Gilmore

unread,
Jan 21, 2019, 6:31:25 PM1/21/19
to pyqtgraph
Hi Patrick,

This solution works well. I really like the floating text that moves along with the lines. 

I am curious to know if there is a way to display the y-axis labels instead of the raw position? 

I passed a tuple array to setTicks to modify the tick labels. I would want to be able to show these values in the Infiniteline text.

yticks=list()
for i in dataFinal:
    pl.plot(i + count)
    yticks.append((count, depths[plotCount]))
    count +=120
    plotCount += 1
ay=pl.getAxis('left')
ay.setTicks([yticks])

Where dataFinal is a list of Numpy arrays containing the raw data

Thank you! 

Greydon

Patrick

unread,
Jan 21, 2019, 7:52:23 PM1/21/19
to pyqtgraph
Hi,

You can display whatever you like in the InfLineLabels, you would just need to manually connect to the InfiniteLine move signal. The code from this question is pretty close:


I think what you want would look something like this (paste in after lr.lines[1].label ... line from above):
lr.lines[0].sigPositionChanged.connect(lambda: line_changed(lr.lines[0]))
lr
.lines[1].sigPositionChanged.connect(lambda: line_changed(lr.lines[1]))

# Pretend this is your list of y labels
yticks
= [[(v, "abcdefghijh"[i]) for i, v in enumerate(np.arange(0, 1.1, 0.1))]]
pl
.getAxis("left").setTicks(yticks)

def line_changed(line):
    ytick_values
= np.array(yticks)[0,:,0].astype(np.float64)
    ytick_labels
= np.array(yticks)[0,:,1]
   
# Get label of tick closest to line position
    line
.label.setText(ytick_labels[np.argmin(np.abs(ytick_values - line.getPos()[1]))])
line_changed
(lr.lines[0])
line_changed
(lr.lines[1])

Patrick
Reply all
Reply to author
Forward
0 new messages