问题
I am trying to get the (x,y) values of my random function plot whenever I move the moused on top of the graph. I am using pyqtgraph.SignalProxy and connect it to a callback mousedMoved.
I am getting this as error: NameError: global name 'mouseMoved' is not defined
Here is the code:
import sys
from pyqtgraph.Qt import QtGui, QtCore
import numpy as np
import pyqtgraph as pg
import time
import random
class TestClass(QtGui.QMainWindow):
#####################################################
def __init__(self):
super(TestClass, self).__init__()
self.initUI()
#####################################################
# GUI construction
def initUI(self):
win = pg.GraphicsWindow(title="Mouse Point, x & y")
# creates plot
self.plot = pg.PlotWidget()
self.plot.setLabel('left', "B", units='T')
self.plot.setLabel('bottom', "t", units='s')
self.plot.showGrid(x=1, y=1, alpha=None)
self.setCentralWidget(win)
self.setGeometry(600, 600, 600, 600)
self.setWindowTitle('Mouse Point, x& y GUI')
# Create some widgets to be placed inside
btnRandon = QtGui.QPushButton('Random Function')
# Create a grid layout to manage the widgets size and position
layout = QtGui.QGridLayout()
win.setLayout(layout)
# Add widgets to the layout in their proper positions
layout.addWidget(btnRandon, 0, 0) # button to show or hide the OldB
layout.addWidget(self.plot, 1, 0)
mypen = pg.mkPen('y', width=1)
self.curve = self.plot.plot(pen=mypen)
# Plot
self.t_plot_max = 30
self.fe = 10e3
self.t = np.arange(-1 * self.t_plot_max, 0, 1.0 / self.fe)
self.len_signal = len(self.t)
self.signal = np.zeros(self.len_signal, dtype=np.double)
# status bar
self.statusBar()
# clicked button evt
btnRandon.clicked.connect(self.buttonRandomClicked)
# show graph
self.show()
#####################################################
def mouseMoved(evt):
mousePoint = self.curve.vb.mapSceneToView(evt[0])
label.setText("<span style='font-size: 14pt; color: white'> x = %0.2f, <span style='color: white'> y = %0.2f</span>" % (mousePoint.x(), mousePoint.y()))
#####################################################
def buttonRandomClicked(self):
print ("Show/Hide OldB")
self.signal = np.random.rand(20)
self.curve.setData(self.signal)
#####################################################
def update(self):
proxy = pg.SignalProxy(self.curve.scene().sigMouseMoved, rateLimit=60, slot=mouseMoved)
self.statusBar().showMessage('Update timer event')
# MAIN ##################################################
def main():
app = QtGui.QApplication(sys.argv)
ex = TestClass()
timer = QtCore.QTimer()
timer.timeout.connect(ex.update)
timer.start(200)
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Amy idea what I'm doing wrong?
Thanks.
回答1:
It is not necessary to use a QTimer
to perform this task and to create a method called update()
since QMainWindow
has a similar method and could be interfering with the correct operation.
The sigMouseMoved
signal is emitted every time you move the mouse, so in general it is not necessary to use the SignalProxy
.
The signal sigMouseMoved
returns the coordinates in pixels with respect to the PlotWidget
, not in the coordinates of the plot, so a conversion must be done using the mapSceneToView
method of the ViewBox
--> PlotItem
--> PlotWidget
.
Finally, it is not necessary to use GraphicsWindow()
, this creates another window, just a QWidget
is enough.
import sys
from pyqtgraph.Qt import QtGui, QtCore
import numpy as np
import pyqtgraph as pg
import random
class TestClass(QtGui.QMainWindow):
#####################################################
def __init__(self):
super(TestClass, self).__init__()
self.initUI()
####################################################
# GUI construction
def initUI(self):
self.setWindowTitle("Mouse Point, x & y")
win = QtGui.QWidget()
# creates plot
self.plot = pg.PlotWidget()
self.plot.setLabel('left', "B", units='T')
self.plot.setLabel('bottom', "t", units='s')
self.plot.showGrid(x=1, y=1, alpha=None)
self.setCentralWidget(win)
self.setGeometry(600, 600, 600, 600)
self.setWindowTitle('Mouse Point, x& y GUI')
# Create some widgets to be placed inside
btnRandon = QtGui.QPushButton('Random Function')
# Create a grid layout to manage the widgets size and position
layout = QtGui.QGridLayout(win)
# Add widgets to the layout in their proper positions
layout.addWidget(btnRandon, 0, 0) # button to show or hide the OldB
layout.addWidget(self.plot, 1, 0)
mypen = pg.mkPen('y', width=1)
self.curve = self.plot.plot(x=[], y=[], pen=mypen)
# Plot
self.t_plot_max = 30
self.fe = 10e3
self.t = np.arange(-1 * self.t_plot_max, 0, 1.0 / self.fe)
self.len_signal = len(self.t)
self.signal = np.zeros(self.len_signal, dtype=np.double)
btnRandon.clicked.connect(self.buttonRandomClicked)
self.curve.scene().sigMouseMoved.connect(self.onMouseMoved)
def onMouseMoved(self, point):
p = self.plot.plotItem.vb.mapSceneToView(point)
self.statusBar().showMessage("{}-{}".format(p.x(), p.y()))
def buttonRandomClicked(self):
print ("Show/Hide OldB")
self.signal = np.random.rand(20)
self.curve.setData(self.signal)
# MAIN ##################################################
def main():
app = QtGui.QApplication(sys.argv)
ex = TestClass()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
回答2:
Sorry, I'm using PyQt5. Try it:
import sys
#from pyqtgraph.Qt import QtGui, QtCore # ---
from PyQt5 import QtWidgets, QtGui, QtCore # +++
import numpy as np
import pyqtgraph as pg
import time
import random
class TestClass(QtGui.QMainWindow):
#####################################################
def __init__(self):
super(TestClass, self).__init__()
self.num = 0 ### +++
self.initUI()
#####################################################
# GUI construction
def initUI(self):
win = pg.GraphicsWindow(title="Mouse Point, x & y")
# creates plot
self.plot = pg.PlotWidget()
self.plot.setLabel('left', "B", units='T')
self.plot.setLabel('bottom', "t", units='s')
self.plot.showGrid(x=1, y=1, alpha=None)
self.setCentralWidget(win)
self.setGeometry(600, 600, 600, 600)
self.setWindowTitle('Mouse Point, x& y GUI')
# Create some widgets to be placed inside
btnRandon = QtGui.QPushButton('Random Function')
# Create a grid layout to manage the widgets size and position
layout = QtGui.QGridLayout()
win.setLayout(layout)
# Add widgets to the layout in their proper positions
layout.addWidget(btnRandon, 0, 0) # button to show or hide the OldB
layout.addWidget(self.plot, 1, 0)
mypen = pg.mkPen('y', width=1)
self.curve = self.plot.plot(pen=mypen)
# Plot
self.t_plot_max = 30
self.fe = 10e3
self.t = np.arange(-1 * self.t_plot_max, 0, 1.0 / self.fe)
self.len_signal = len(self.t)
self.signal = np.zeros(self.len_signal, dtype=np.double)
# status bar
self.statusBar()
# clicked button evt
btnRandon.clicked.connect(self.buttonRandomClicked)
# show graph
self.show()
# ### ------------------------------------------------
# def mouseMoved(evt):
# mousePoint = self.curve.vb.mapSceneToView(evt[0])
# label.setText("<span style='font-size: 14pt; color: white'> x = %0.2f, <span style='color: white'> y = %0.2f</span>" % (mousePoint.x(), mousePoint.y()))
#####################################################
def buttonRandomClicked(self):
print ("Show/Hide OldB")
self.signal = np.random.rand(20)
self.curve.setData(self.signal)
#####################################################
# def update(self):
# proxy = pg.SignalProxy(self.curve.scene().sigMouseMoved, rateLimit=60, slot=mouseMoved)
# self.statusBar().showMessage('Update timer event')
### vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
def update(self):
### +++++++++++++++++++++++++++++++++++++++++++++
def mouseMoved(evt):
print("-->> def mouseMoved(evt):", evt)
print("\tevt.x()=`{}`, evt.y()=`{}`".format(evt.x(), evt.y()))
# AttributeError: 'PlotDataItem' object has no attribute 'vb' ### ???????
#mousePoint = self.curve.vb.mapSceneToView(evt[0])
# vvvv - > label what is it? <-- NameError: name `label` is not defined ### ???????
#label.setText("<span style='font-size: 14pt; color: white'> x = %0.2f, <span style='color: white'> y = %0.2f</span>" % (mousePoint.x(), mousePoint.y()))
self.source = self.curve.scene().sigMouseMoved
#print(" source ", self.source)
proxy = pg.SignalProxy(self.source, rateLimit=60, slot=mouseMoved) #+self
#print("def update(self):222", proxy)
if self.source is None:
pass
#sp.connect(sp, QtCore.SIGNAL('signal'), slot)
else:
#sp.connect(sp, signal, slot)
proxy.signal.connect(mouseMoved)
self.statusBar().showMessage('Update timer event `{}`'.format(self.num))
self.num += 1
return proxy
# MAIN ##################################################
def main():
app = QtGui.QApplication(sys.argv)
ex = TestClass()
timer = QtCore.QTimer()
timer.timeout.connect(ex.update)
timer.start(200)
sys.exit(app.exec_())
if __name__ == '__main__':
main()
来源:https://stackoverflow.com/questions/50833107/mouse-coordinates-of-pytqt-graph-line