问题描述
我尝试使用对数刻度实现可点击的多重绘图。 因为我想让图可点击,所以我使用了 PlotCurveItem() 和 addItem 而不是仅仅使用 plot()。但不幸的是,如果我将 SetLogMode 与 PlotCurveItem() 一起使用,x 轴和 y 轴将具有几乎无限的值(实际上,it is not displayed in logarithmic)。当我使用 plot() 时不会发生这样的问题。
有什么解决办法吗?或者你知道其他用对数刻度实现可点击多图的好方法吗?谢谢。
app = QtGui.QApplication([])
w = pg.GraphicslayoutWidget(show=True)
w.resize(800,800)
p1 = w.addplot(0,title="p1")
p1.setLogMode(True,True)
temp_curve = pg.PlotCurveItem(y=2*x,pen=pg.mkPen(pg.mkColor(str(color[0]))),width=4,clickable=True)
temp_curve2 = pg.PlotCurveItem(y=3*x,pen=pg.mkPen(pg.mkColor(str(color[1]))),clickable=True)
p1.addItem(temp_curve)
p1.addItem(temp_curve2)
解决方法
问题和解决方案
这里有很多问题。
问题
- 当您更改
Plot
小部件的比例时,它不会更新PlotCurveItem
上的数据。然后你有相同的曲线,但轴比例错误。它在您使用plot()
时有效,因为它创建了一个PlotDataItem
而不是PlotCurveItem
,下面我将对此进行更多解释。
方案一(不方便)
- 在PlotDataItem's doc.里面创建一个类似
getData()
的函数来获取数据,将其转换为对数/线性模式,然后每次更改时再次将数据设置到PlotCurveItem
中规模。这可能会很混乱。
方案二(更方便)
- 您可以改用
PlotDataItem
,因为它会生成PlotCurveItem
作为其中的一部分(请阅读:PlotCurveItem's doc. 和 PlotDataItem's doc.)。当您更改比例时,此PlotDataItem
会更新绘图数据。因为这就是它的工作方式。如果您想知道比例的变化是如何工作的,我建议您阅读PlotDataItem's source code。实现这一点,您可以使用以下方法创建图:
curve_1 = pg.PlotDataItem(
x,y1,pen=pg.mkPen(pg.mkColor((70,70,30))),width=4 #,clickable = True <-- This don't work
)
curve_2 = pg.PlotDataItem(
x,y2,70))),clickable = True <-- This don't work
)
方案二的问题(及其方案)
- 现在出现了一个新问题,这个
PlotDataItem
有一个小错误。它在被点击时有信号,但从不激活在其中创建的PlotCurveItem
的“可点击”属性。尽管您传递了clickable = True
参数,但这将导致您在单击绘图时永远不会得到响应。 - 我们可以做很多事情来解决这个问题,最好的和通用的解决方案将意味着在
__init__()
的PlotDataItem()
构建器中进行大量的返工。但是考虑到您想要使用对数刻度实现 clickable 多个图,我们可以强制它是可点击的。为此,我们必须在 PlotDataItem 中设置曲线项的可点击属性:
curve_1.curve.setClickable(True)
curve_2.curve.setClickable(True)
- 现在您可以连接
sigClicked
发出的信号 (PlotCurveItem
),如下所示:
curve_1.sigClicked.connect(curve_1_clicked)
curve_2.sigClicked.connect(curve_2_clicked)
def curve_1_clicked(ev):
print('Curve 1 clicked')
## Do more things...
def curve_1_clicked(ev):
print('Curve 2 clicked')
## Do more things...
我使用与您不同的代码对其进行了测试,使用 PlotWidget
并使用对象来构建 GUI,但它的工作方式必须相同。这是我的代码:
import sys
import pyqtgraph as pg
import numpy as np
from PyQt5 import QtWidgets
class MyApp(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
lay = QtWidgets.QVBoxLayout()
self.setLayout(lay)
self.glw = pg.PlotWidget(show=True)
lay.addWidget(self.glw)
x = np.arange(100)
y1 = 2*x
y2 = 3*x**3
self.curve_1 = pg.PlotDataItem(
x,clickable = True <-- This don't work
)
self.curve_2 = pg.PlotDataItem(
x,clickable = True <-- This don't work
)
self.curve_1.curve.setClickable(True)
self.curve_2.curve.setClickable(True)
self.glw.addItem(self.curve_1)
self.glw.addItem(self.curve_2)
# self.glw.setLogMode(False,False)
self.glw.setLogMode(True,True)
self.curve_1.sigClicked.connect(self.c1click)
self.curve_2.sigClicked.connect(self.c2click)
def c1click(self,ev):
print('Curve 1 clicked')
def c2click(self,ev):
print('Curve 2 clicked')
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MyApp()
window.show()
sys.exit(app.exec_())