如何将自定义 AxisItem 添加到现有的 PlotWidget?
How to add custom AxisItem to existing PlotWidget?
我正在尝试将 pyqtgraph 中的自定义 AxisItem 添加到由 Qt Designer 生成的现有 PlotWidget。有相关主题here,但没有代码示例的确切答案,我无法发表评论,所以我创建了一个新主题。
这是我的自定义 AxisItem(基于 this 代码):
import pyqtgraph as pg
import datetime
def int2td(ts):
return(datetime.timedelta(seconds=float(ts)/1e6))
class TimeAxisItem(pg.AxisItem):
def __init__(self, *args, **kwargs):
super(TimeAxisItem, self).__init__(*args, **kwargs)
def tickStrings(self, values, scale, spacing):
return [int2dt(value).strftime("%H:%M:%S") for value in values]
这是我的主要 QtPlotter class:
from pyqtgraph.Qt import QtGui
from template_pyqt import Ui_Form # Ui_Form is generated by Qt Designer
class QtPlotter:
def __init__(self):
self.app = QtGui.QApplication([])
self.win = QtGui.QWidget()
self.ui = Ui_Form()
self.ui.setupUi(self.win)
self.win.show()
self.ui_plot = self.ui.plot
self.ui_plot.showGrid(x=True, y=True)
然后我尝试添加我的自定义 AxisItem:
self.ui_plot.getPlotItem().axes['bottom']['item'] = TimeAxisItem(orientation='bottom')
我没有错误,但这没有任何效果。
PlotItem
class没有setAxis
方法,只有getAxis
方法获取当前坐标轴。您可以在 PlotItem
构造函数的 axisItems
参数中指定带有轴项的字典,但似乎无法更新现有 PlotItem
的 AxisItem
。
尽管 PlotItem.axes
字典是一个 public 属性,但它没有记录在案,因此仅使用它会有一点风险。 PyQtGraph 的作者有可能会改变它的行为,或者重命名它(尽管这种情况发生的可能性很小)。恕我直言,它应该成为私有属性。
在任何情况下,通过查看 PlotItem
构造函数的 source,您可以看到如何将来自 axisItem
参数的轴项添加到绘图项:
## Create and place axis items
if axisItems is None:
axisItems = {}
self.axes = {}
for k, pos in (('top', (1,1)), ('bottom', (3,1)), ('left', (2,0)), ('right', (2,2))):
if k in axisItems:
axis = axisItems[k]
else:
axis = AxisItem(orientation=k, parent=self)
axis.linkToView(self.vb)
self.axes[k] = {'item': axis, 'pos': pos}
self.layout.addItem(axis, *pos)
axis.setZValue(-1000)
axis.setFlag(axis.ItemNegativeZStacksBehindParent)
也许您可以通过查看上面的代码使其工作。同样,这是无证行为,使用风险自负!此外,您应该在设置新的 AxisItem
时正确删除和取消链接以防止内存泄漏。也许这很棘手,这可能是 PlotItem.setAxis
方法不存在的原因。
我研究了 PlotItem
构造函数的 source 一整天,但我无法让它工作。
最后发现QtDesigner/QtCreator在PlotWidget上只输出了三行。与其尝试将 TimeAxisItem 添加到现有的 PlotWidget,不如删除现有的 PlotWidget 然后使用 TimeAxisItem 创建一个新的 PlotWidget 更容易(但绝对不是更好),如 .
所述
from PyQt5 import QtCore
import pyqtgraph as pg
parent = self.ui_plot.parent()
geom_object = self.ui_plot.frameGeometry()
geometry = QtCore.QRect(geom_object.left(), geom_object.top(), geom_object.width(), geom_object.height())
object_name = self.ui_plot.objectName()
del self.ui_plot
time_axis = TimeAxisItem(orientation='bottom')
self.ui_plot = pg.PlotWidget(parent, axisItems={'bottom': time_axis})
self.ui_plot.setGeometry(geometry)
self.ui_plot.setObjectName(object_name)
既然有人试图在这里找到东西,我将 post 我的简单但不优雅的解决方法。
使用 pyuic 将 Qt Designer 生成的模板转换为 python 模板文件后,我通过替换相应的 PlotWidget 将自定义 AxisItem 直接添加到 python 模板文件。这一切都可以通过简单的 bash 脚本来完成:
pyuic4 template.ui -o template.py
match="from PyQt4 import QtCore, QtGui"
insert_class="from timeaxisitem_class import TimeAxisItem"
match_widget="self.plot = PlotWidget(Form)"
insert_timeaxis="self.plot = PlotWidget(Form, axisItems={'bottom': TimeAxisItem(orientation='bottom')})"
file="template.py"
sed -i "s/$match/$match\n$insert_class/" $file
sed -i "s/$match_widget/$insert_timeaxis/" $file
我知道这是一个旧的 post 但我遇到了类似的问题并在 this gist example 中找到了解决方案,它是一个实现 attachToPlotItem
方法的 AxisItem 子类。
所以关于原来的post,而不是
self.ui_plot.getPlotItem().axes['bottom']['item'] = TimeAxisItem(orientation='bottom')
您的 TimeAxisItem 子类中需要以下方法(从上面链接的示例复制):
def attachToPlotItem(self, plotItem):
"""Add this axis to the given PlotItem
:param plotItem: (PlotItem)
"""
self.setParentItem(plotItem)
viewBox = plotItem.getViewBox()
self.linkToView(viewBox)
self._oldAxis = plotItem.axes[self.orientation]['item']
self._oldAxis.hide()
plotItem.axes[self.orientation]['item'] = self
pos = plotItem.axes[self.orientation]['pos']
plotItem.layout.addItem(self, *pos)
self.setZValue(-1000)
它甚至保留了原始的 AxisItem,以便在需要时可以重新设置。
然后在您的 QtPlotter 构造函数中,您将添加
axis = TimeAxisItem(orientation='bottom')
axis.attactToPlotItem(self.ui_plot.getPlotItem())
太简单了。 PlotItem class 没有 setAxis 方法。取而代之的是一个名为 setAxisItems 的方法。这段代码对我有用。
date_axis = pg.graphicsItems.DateAxisItem.DateAxisItem(orientation = 'bottom')
self.mainSoundPlot.setAxisItems(axisItems = {'bottom': date_axis})
我正在尝试将 pyqtgraph 中的自定义 AxisItem 添加到由 Qt Designer 生成的现有 PlotWidget。有相关主题here,但没有代码示例的确切答案,我无法发表评论,所以我创建了一个新主题。
这是我的自定义 AxisItem(基于 this 代码):
import pyqtgraph as pg
import datetime
def int2td(ts):
return(datetime.timedelta(seconds=float(ts)/1e6))
class TimeAxisItem(pg.AxisItem):
def __init__(self, *args, **kwargs):
super(TimeAxisItem, self).__init__(*args, **kwargs)
def tickStrings(self, values, scale, spacing):
return [int2dt(value).strftime("%H:%M:%S") for value in values]
这是我的主要 QtPlotter class:
from pyqtgraph.Qt import QtGui
from template_pyqt import Ui_Form # Ui_Form is generated by Qt Designer
class QtPlotter:
def __init__(self):
self.app = QtGui.QApplication([])
self.win = QtGui.QWidget()
self.ui = Ui_Form()
self.ui.setupUi(self.win)
self.win.show()
self.ui_plot = self.ui.plot
self.ui_plot.showGrid(x=True, y=True)
然后我尝试添加我的自定义 AxisItem:
self.ui_plot.getPlotItem().axes['bottom']['item'] = TimeAxisItem(orientation='bottom')
我没有错误,但这没有任何效果。
PlotItem
class没有setAxis
方法,只有getAxis
方法获取当前坐标轴。您可以在 PlotItem
构造函数的 axisItems
参数中指定带有轴项的字典,但似乎无法更新现有 PlotItem
的 AxisItem
。
尽管 PlotItem.axes
字典是一个 public 属性,但它没有记录在案,因此仅使用它会有一点风险。 PyQtGraph 的作者有可能会改变它的行为,或者重命名它(尽管这种情况发生的可能性很小)。恕我直言,它应该成为私有属性。
在任何情况下,通过查看 PlotItem
构造函数的 source,您可以看到如何将来自 axisItem
参数的轴项添加到绘图项:
## Create and place axis items
if axisItems is None:
axisItems = {}
self.axes = {}
for k, pos in (('top', (1,1)), ('bottom', (3,1)), ('left', (2,0)), ('right', (2,2))):
if k in axisItems:
axis = axisItems[k]
else:
axis = AxisItem(orientation=k, parent=self)
axis.linkToView(self.vb)
self.axes[k] = {'item': axis, 'pos': pos}
self.layout.addItem(axis, *pos)
axis.setZValue(-1000)
axis.setFlag(axis.ItemNegativeZStacksBehindParent)
也许您可以通过查看上面的代码使其工作。同样,这是无证行为,使用风险自负!此外,您应该在设置新的 AxisItem
时正确删除和取消链接以防止内存泄漏。也许这很棘手,这可能是 PlotItem.setAxis
方法不存在的原因。
我研究了 PlotItem
构造函数的 source 一整天,但我无法让它工作。
最后发现QtDesigner/QtCreator在PlotWidget上只输出了三行。与其尝试将 TimeAxisItem 添加到现有的 PlotWidget,不如删除现有的 PlotWidget 然后使用 TimeAxisItem 创建一个新的 PlotWidget 更容易(但绝对不是更好),如
from PyQt5 import QtCore
import pyqtgraph as pg
parent = self.ui_plot.parent()
geom_object = self.ui_plot.frameGeometry()
geometry = QtCore.QRect(geom_object.left(), geom_object.top(), geom_object.width(), geom_object.height())
object_name = self.ui_plot.objectName()
del self.ui_plot
time_axis = TimeAxisItem(orientation='bottom')
self.ui_plot = pg.PlotWidget(parent, axisItems={'bottom': time_axis})
self.ui_plot.setGeometry(geometry)
self.ui_plot.setObjectName(object_name)
既然有人试图在这里找到东西,我将 post 我的简单但不优雅的解决方法。
使用 pyuic 将 Qt Designer 生成的模板转换为 python 模板文件后,我通过替换相应的 PlotWidget 将自定义 AxisItem 直接添加到 python 模板文件。这一切都可以通过简单的 bash 脚本来完成:
pyuic4 template.ui -o template.py
match="from PyQt4 import QtCore, QtGui"
insert_class="from timeaxisitem_class import TimeAxisItem"
match_widget="self.plot = PlotWidget(Form)"
insert_timeaxis="self.plot = PlotWidget(Form, axisItems={'bottom': TimeAxisItem(orientation='bottom')})"
file="template.py"
sed -i "s/$match/$match\n$insert_class/" $file
sed -i "s/$match_widget/$insert_timeaxis/" $file
我知道这是一个旧的 post 但我遇到了类似的问题并在 this gist example 中找到了解决方案,它是一个实现 attachToPlotItem
方法的 AxisItem 子类。
所以关于原来的post,而不是
self.ui_plot.getPlotItem().axes['bottom']['item'] = TimeAxisItem(orientation='bottom')
您的 TimeAxisItem 子类中需要以下方法(从上面链接的示例复制):
def attachToPlotItem(self, plotItem):
"""Add this axis to the given PlotItem
:param plotItem: (PlotItem)
"""
self.setParentItem(plotItem)
viewBox = plotItem.getViewBox()
self.linkToView(viewBox)
self._oldAxis = plotItem.axes[self.orientation]['item']
self._oldAxis.hide()
plotItem.axes[self.orientation]['item'] = self
pos = plotItem.axes[self.orientation]['pos']
plotItem.layout.addItem(self, *pos)
self.setZValue(-1000)
它甚至保留了原始的 AxisItem,以便在需要时可以重新设置。
然后在您的 QtPlotter 构造函数中,您将添加
axis = TimeAxisItem(orientation='bottom')
axis.attactToPlotItem(self.ui_plot.getPlotItem())
太简单了。 PlotItem class 没有 setAxis 方法。取而代之的是一个名为 setAxisItems 的方法。这段代码对我有用。
date_axis = pg.graphicsItems.DateAxisItem.DateAxisItem(orientation = 'bottom')
self.mainSoundPlot.setAxisItems(axisItems = {'bottom': date_axis})