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

8 人关注

我正在尝试添加自定义 轴项目 在pyqtgraph中对现有的 PlotWidget 由Qt Designer生成的。有一个相关的主题 here ,但没有确切的答案与代码例子,我也无法评论,所以我创建了一个新的主题。

This is my custom 轴项目 (根据 this code):

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)

然后我试图添加我的自定义轴项目:

self.ui_plot.getPlotItem().axes['bottom']['item'] = TimeAxisItem(orientation='bottom')

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

1 个评论
use deleteLater() work for me better! see: stackoverflow.com/questions/4528347/...
python
python-2.7
pyqt
pyqt4
pyqtgraph
enclis
enclis
发布于 2017-03-19
5 个回答
Yasin Arabi
Yasin Arabi
发布于 2018-09-04
已采纳
0 人赞同

这是很容易的。的 PlotItem 类没有一个 setAxis 方法。取而代之的是,有一个名为 SetAxisItems . this code worked for me.

date_axis = pg.graphicsItems.DateAxisItem.DateAxisItem(orientation = 'bottom')
self.mainSoundPlot.setAxisItems(axisItems = {'bottom': date_axis})
    
很好!早在2017年,就没有这种方法。
LC_
LC_
发布于 2018-09-04
0 人赞同

我知道这是个老帖子,但我遇到了一个类似的问题,并在以下网站看到了一个解决方案 这个gist例子 ,这是一个AxisItem子类,实现了一个 attachToPlotItem 方法。

因此,关于原来的帖子,而不是

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())
    
titusjan
titusjan
发布于 2018-09-04
0 人赞同

PlotItem 类没有一个 setAxis 方法,只有一个 getAxis 方法来获取当前轴。你可以在 PlotItem 构造函数的 axisItems 参数中指定一个包含轴项的字典,但似乎不可能更新现有 PlotItem AxisItem

尽管 PlotItem.axes 字典是一个公共属性,但它是没有文档的,因此仅仅使用它是有一点风险的。PyQtGraph的作者有可能会改变它的行为,或者重新命名它(尽管这种情况发生的可能性很小)。IMHO,它应该被做成一个私有属性。

在任何情况下,通过查看 source PlotItem 构造函数中,你可以看到来自 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时,你应该正确地删除和解除旧的AxisItem的链接,以防止内存泄漏。也许这很棘手,这可能是PlotItem.setAxis方法不存在的原因。

boudewijn21
boudewijn21
发布于 2018-09-04
0 人赞同

I looked into the source PlotItem 构造函数整整一天,但我无法让它工作。

最后,我发现QtDesigner/QtCreator只在PlotWidget上输出三行。与其尝试在现有的PlotWidget上添加一个TimeAxisItem,不如直接删除现有的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)
    
enclis
enclis
发布于 2018-09-04
0 人赞同

既然有人试图在这里找东西,我就把我简单但不优雅的解决方法贴出来。

在用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')})"