ViewBox and mouse coordinates

56 views
Skip to first unread message

Bertram Gilfoyle

unread,
May 8, 2020, 6:59:35 PM5/8/20
to pyqtgraph
Is there a way to find out which viewbox or widget the current mouse coordinates are on?

I'm plotting multiple viewboxes, each with one widget inside, then using SignalProxy to capture sigMouseMoved signals.
With one viewbox, it's simple but I'm pulling hairs on how to do it with multiple. Goal is to display a simple tooltip (TextItem).

Edmondo Giovannozzi

unread,
May 9, 2020, 10:00:09 AM5/9/20
to pyqtgraph
I have solved it this way:

class MousePosition(QtCore.QObject):
   
def __init__(self, status_bar, pl, labels):
       
super().__init__()
       
self.pl = pl
       
self.status_bar = status_bar
       
self.labels = labels
       
self.proxy = pg.SignalProxy(pl.scene().sigMouseMoved, rateLimit=10, slot=self.mousemoved)


   
def mousemoved(self, evt):
        pos
= evt[0]
       
if self.pl.sceneBoundingRect().contains(pos):
            mousePoint
= self.pl.vb.mapSceneToView(pos)
           
self.status_bar.set_x(mousePoint.x(),self.labels[0])
           
self.status_bar.set_y(mousePoint.y(),self.labels[1])
           
class StatusBarKK3:
   
def __init__(self, window, plots):
       
self.window = window
       
self.plots = plots
       
self.status_bar = window.statusBar()
       
       
self.x_label = QtWidgets.QLabel("x: ")
       
self.y_label = QtWidgets.QLabel("y: ")
       
       
self.status_bar.addPermanentWidget(self.x_label)
       
self.status_bar.addPermanentWidget(self.y_label)
       
self.mouse_position = {}
       
for (name,pl),labels in plots.items():
           
self.mouse_position[pl] = MousePosition(self, pl, labels)
           
   
def set_x(self, x, prefix='x'):
       
self.x_label.setText(f"{prefix}: {x:8.5g}  ")
   
   
def set_y(self, y, prefix='y'):
       
self.y_label.setText(f"{prefix}: {y:8.5g}  ")


Where plots is a dict with keys being (name, plotItem) and value a string that I want to show  for the x and y coordinates on the status bar. At the moment name is not used and I may delete it.

Cheers,

Edmondo Giovannozzi

unread,
May 9, 2020, 10:05:55 AM5/9/20
to pyqtgraph
The plotsdictionary could be something like:

plots = {('Spectrum', spectrum_plot):('t','f'),
         ('Amplitude', amplitude_plot):('t','B')}

where spectrum_plot and amplitude_plot are plotItem object.

Bertram Gilfoyle

unread,
May 10, 2020, 3:27:40 AM5/10/20
to pyqtgraph

Looks great, thank you.

Bertram Gilfoyle

unread,
May 10, 2020, 1:27:23 PM5/10/20
to pyqtgraph

This is what I ended up with, almost identical what you provided.
The TextItem pulls values from a pandas column. There's also a vertical line as an X axis highlighter. PlotIndicators is initiated in a Main function (just a dict).
I haven't found a more intelligent way to hide the items when cursor is not in the scene. Main.chart.add does plot.addItem(item) in GraphicsLayoutWidget, refresh does 'clear' first.


class MousePosition(QObject):
   def __init__(self, plot, name):
       super().__init__()
       self.plot = plot
       self.name = name
       self.proxy = pg.SignalProxy(plot.scene().sigMouseMoved, rateLimit=60, slot=self.mouseMoved)

    def mouseMoved(self, event):
       pos = event[0]
       if self.plot.sceneBoundingRect().contains(pos):
           Main.plotIndicators.labels[self.name].show()
           Main.plotIndicators.cross[self.name].show()
           Main.plotIndicators.labelCoords(self.plot.vb.mapSceneToView(pos), self.name)
       else:
           Main.plotIndicators.labels[self.name].hide()
           Main.plotIndicators.cross[self.name].hide()


...


        for name, val in self.plottedIndicators.items():
           label =                 pg.TextItem('', color="#edede6", anchor=(-0.3, 1.5),
                                               border=pg.mkPen('#fcfcfc'), fill="#443a2e")
           self.labels[name] =     Main.chart.add(val['plt'], label)

            cross =                 pg.InfiniteLine(angle=90, movable=False,
                                                   pen={"color": "#8080ff"})
           self.cross[name] =      Main.chart.add(val['plt'], cross)

            self.mp[val['plt']] =   MousePosition(val['plt'], name)

   
def labelCoords(self, mp, name):
       index =     int(mp.x() + 0.5) - 1
       col =       self.plottedIndicators[name]['col']
       self.labels[name].setText(f'{self._charts[col].iloc[index].astype(str)}')
       self.labels[name].setPos(mp)
       self.cross[name].setPos(mp)





On Saturday, May 9, 2020 at 10:00:09 PM UTC+8, Edmondo Giovannozzi wrote:
Reply all
Reply to author
Forward
0 new messages