PyQt6基础_pyqtgraph_折线图with缩放调节

目录

字符型横坐标代码

折线图代码

运行


创建新类,继承pg.PlotWidget,在新类中实现业务内容,重写pg.PlotWidget中的wheelEvent方法并使用业务数据实现比较理想的缩放状态。

字符型横坐标代码

复制代码
class StrAxisItem(pg.AxisItem):
    def __init__(self,ticks,*args,**kwargs):
        pg.AxisItem.__init__(self,*args,**kwargs)
        self.x_values = [x[0] for x in ticks]
        self.x_strings = [x[1] for x in ticks]
        pass
    def tickStrings(self, values, scale, spacing):
        strings = []
        for v in values:
            vs = v*scale
            if vs in self.x_values:
                vstr = self.x_strings[self.x_values.index(vs)]
            else:
                vstr = ''
            strings.append(vstr)
        return strings

折线图代码

复制代码
class LineGraphWidget(pg.PlotWidget):
    def __init__(self):
        super().__init__()
        self.init_data()
        pass
    def init_data(self):
        self.whole_df:pd.DataFrame = pd.DataFrame()
        self.color_one = (30,144,255)
        self.color_two = (138,43,226)
        self.color_three = (220,20,60)
        pass
    def set_data(self,df:pd.DataFrame):
        self.clear()
        self.addLegend()

        self.whole_df = df

        x = df['x'].to_list()
        xTicks = df.loc[:, ['x', 'date']].values
        y_dict = {
            'one': df['one'].to_list(),
            'two': df['two'].to_list(),
            'three': df['three'].to_list()
        }

        one_curve = pg.PlotCurveItem(x=np.array(x),y=np.array(y_dict['one']),pen=pg.mkPen({'color':self.color_one}),connect='finite',name='one')
        two_curve = pg.PlotCurveItem(x=np.array(x),y=np.array(y_dict['two']),pen=pg.mkPen({'color':self.color_two}),connect='finite',name='two')
        three_curve = pg.PlotCurveItem(x=np.array(x),y=np.array(y_dict['three']),pen=pg.mkPen({'color':self.color_three}),connect='finite',name='three')

        horAxis = StrAxisItem(ticks=xTicks, orientation='bottom')
        self.setAxisItems({'bottom':horAxis})

        self.addItem(one_curve)
        self.addItem(two_curve)
        self.addItem(three_curve)

        self.vLine = pg.InfiniteLine(angle=90,movable=False)
        self.hLine = pg.InfiniteLine(angle=0,movable=False)
        self.label = pg.TextItem()

        self.addItem(self.vLine,ignoreBounds=True)
        self.addItem(self.hLine,ignoreBounds=True)
        self.addItem(self.label,ignoreBounds=True)

        self.vb = self.getViewBox()
        self.proxy = pg.SignalProxy(self.scene().sigMouseMoved, rateLimit=60, slot=self.pw_mouseMoved)
        self.enableAutoRange()
        pass
    def pw_mouseMoved(self, evt):
        pos = evt[0]
        if self.sceneBoundingRect().contains(pos):
            mousePoint = self.vb.mapSceneToView(pos)
            index = int(mousePoint.x())
            if index>=0 and index<len(self.whole_df):
                html_str = ''
                html_str += f"<br/>日期:{self.whole_df.loc[self.whole_df['x']==index].iloc[0]['date']}"
                html_str += f"<br/>one:{self.whole_df.loc[self.whole_df['x']==index].iloc[0]['one']}"
                html_str += f"<br/>two:{self.whole_df.loc[self.whole_df['x']==index].iloc[0]['two']}"
                html_str += f"<br/>three:{self.whole_df.loc[self.whole_df['x']==index].iloc[0]['three']}"

                self.label.setHtml(html_str)
                self.label.setPos(mousePoint.x(),mousePoint.y())
                pass
            self.vLine.setPos(mousePoint.x())
            self.hLine.setPos(mousePoint.y())
        pass
    def wheelEvent(self,ev):
        if len(self.whole_df) <= 0:
            super().wheelEvent(ev)
        else:
            delta = ev.angleDelta().x()
            if delta == 0:
                delta = ev.angleDelta().y()

            s = 1.001 ** delta

            before_xmin, before_xmax = self.viewRange()[0]
            val_x = self.getViewBox().mapSceneToView(ev.position()).x()

            after_xmin = int(val_x - (val_x - before_xmin) // s)
            after_xmax = int(val_x + (before_xmax - val_x) // s)

            if after_xmin < 1:
                after_xmin = 0
            if after_xmin >= len(self.whole_df):
                after_xmin = max(len(self.whole_df) - 3, len(self.whole_df) - 1)
            if after_xmax < 1:
                after_xmax = min(len(self.whole_df) - 1, 1)
            if after_xmax >= len(self.whole_df):
                after_xmax = len(self.whole_df) - 1

            # print(after_xmin, after_xmax)

            df00 = self.whole_df.loc[(self.whole_df['x'] >= after_xmin) & (self.whole_df['x'] <= after_xmax)].copy()
            after_ymin = min(df00['one'].min(), df00['two'].min(), df00['three'].min())
            after_ymax = max(df00['one'].max(), df00['two'].max(), df00['three'].max())
            self.setXRange(after_xmin, after_xmax)
            self.setYRange(after_ymin, after_ymax)
            pass
    pass

运行

复制代码
if __name__ == '__main__':
    df = pd.DataFrame(data={
        'date':['2020-01-01','2021-01-01','2022-01-01','2023-01-01','2024-01-01'],
        'one':[1,5,12,8,3],
        'two':[-9,2,4,8,-10],
        'three':[-1,5,8,10,-5]
    })
    df['x'] = range(len(df))

    app = QApplication([])
    pw = LineGraphWidget()
    pw.set_data(df.copy())
    pw.show()
    app.exec()
    pass
相关推荐
墨绿色的摆渡人21 分钟前
pytorch小记(二十一):PyTorch 中的 torch.randn 全面指南
人工智能·pytorch·python
大叔_爱编程25 分钟前
p024基于Django的网上购物系统的设计与实现
python·django·vue·毕业设计·源码·课程设计·网上购物系统
一个天蝎座 白勺 程序猿33 分钟前
Python爬虫(29)Python爬虫高阶:动态页面处理与云原生部署全链路实践(Selenium、Scrapy、K8s)
redis·爬虫·python·selenium·scrapy·云原生·k8s
90后小陈老师33 分钟前
WebXR教学 09 项目7 使用python从0搭建一个简易个人博客
开发语言·python·web
weixin-WNXZ02181 小时前
闲上淘 自动上货工具运行原理解析
爬虫·python·自动化·软件工程·软件需求
正在走向自律1 小时前
Conda 完全指南:从环境管理到工具集成
开发语言·python·conda·numpy·fastapi·pip·开发工具
lqjun08271 小时前
PyTorch实现CrossEntropyLoss示例
人工智能·pytorch·python
DpHard2 小时前
Vscode 配置python调试环境
ide·vscode·python
小蜗笔记2 小时前
显卡、Cuda和pytorch兼容问题
人工智能·pytorch·python
高建伟-joe2 小时前
内容安全:使用开源框架Caffe实现上传图片进行敏感内容识别
人工智能·python·深度学习·flask·开源·html5·caffe