如何将自定义 AxisItem 添加到现有的 PlotWidget?

Posted

技术标签:

【中文标题】如何将自定义 AxisItem 添加到现有的 PlotWidget?【英文标题】:How to add custom AxisItem to existing PlotWidget? 【发布时间】:2017-08-10 17:48:58 【问题描述】:

我正在尝试将 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 类:

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')

我没有错误,但这没有任何效果。

【问题讨论】:

使用deleteLater() 更好地为我工作!见:***.com/questions/4528347/… 【参考方案1】:

这太容易了。 PlotItem 类没有 setAxis 方法。取而代之的是一个名为 setAxisItems 的方法。这段代码对我有用。

date_axis = pg.graphicsItems.DateAxisItem.DateAxisItem(orientation = 'bottom')
self.mainSoundPlot.setAxisItems(axisItems = 'bottom': date_axis)

【讨论】:

不错!早在 2017 年就没有这种方法。【参考方案2】:

我知道这是一篇旧帖子,但我遇到了类似的问题,并在 this gist example 中找到了一个解决方案,它是一个实现 attachToPlotItem 方法的 AxisItem 子类。

所以关于原始帖子,而不是

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())

【讨论】:

【参考方案3】:

PlotItem 类没有setAxis 方法,只有getAxis 方法来获取当前轴。您可以在PlotItem 构造函数的axisItems 参数中指定带有轴项的字典,但似乎无法更新现有AxisItemAxisItem

尽管PlotItem.axes 字典是公共属性,但它没有记录在案,因此仅使用它有点冒险。 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 方法不存在的原因。

【讨论】:

【参考方案4】:

我查看PlotItem 构造函数的source 整整一天,但我无法让它工作。

最后发现QtDesigner/QtCreator在PlotWidget上只输出了三行。与其尝试将 TimeAxisItem 添加到现有的 PlotWidget,不如删除现有的 PlotWidget,然后使用 TimeAxisItem 创建一个新的 PlotWidget 更容易(但绝对不是更好),如 here 所述。

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)

【讨论】:

【参考方案5】:

由于有人试图在这里找到一些东西,我将发布我的简单但不优雅的解决方法。

在使用 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

【讨论】:

以上是关于如何将自定义 AxisItem 添加到现有的 PlotWidget?的主要内容,如果未能解决你的问题,请参考以下文章

如何将自定义标签/过滤器添加到现有的 Django 应用程序?

如何将 SRW 包添加到现有的 Oracle 数据库?

如何将 qml ScatterSeries 添加到现有的 qml 定义的 ChartView?

如何将熊猫数据添加到现有的 csv 文件中?

如何将多维数组添加到现有的 Spark DataFrame

如何将 Mailchimp 添加到现有的注册框