首页 > 编程问答 >如何动态更改pyqtgraph中的文本

如何动态更改pyqtgraph中的文本

时间:2024-09-24 21:24:33浏览次数:1  
标签:python pyqt pyqt5 pyqtgraph

我正在尝试创建一个继承 pyqthraph TextItem 类的自定义类,以便我可以拥有多行,每行具有不同的颜色,就像仅 1 个 TextItem 对象一样。我希望能够在类中存储行位置和颜色的逻辑,基本上,如果删除文本行,所有后续行都会向上移动。

下面的代码概要是:它是一种随机游走,绘制当前价格并更新每次迭代。在 6 次迭代中,新价格 sub1_value 作为新线添加到图中并进行更新。在 8 次迭代时添加另一个, sub2_value 然后,在 10 次迭代时,删除 sub1,将 sub2 价格移至 sub1 的位置,然后在 14 次迭代时删除 sub2 价格。

问题是旧文本行(sub1 和 sub2 价格)仍然存在。第一行 main 发生变化,但值 sub1 sub2 的线无论其最后的值是什么,都保留在绘图上。我打算删除 sub1,然后将 sub2 放在第 2 行(索引 = 1)中,然后删除 sub2,仅显示主(红色)数字。

我已放入打印以查看 html 文本并且这些行被删除,但每当主要价格更新时就会再次重新引入

import sys
import numpy as np
import pyqtgraph as pg
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QTimer

class CustomTextItem(pg.TextItem):
    
    def __init__(self, *args, **kwargs):
        """
        
        self.stock_line_mapping to find the correct line in the html text that corresponds to the stock of the text 
        self.stock_colour_mapping to find the correct colour in the html text that corresponds to the stock of the text 
        self.number_of_lines how many lines of text is present
        
        """
        self.stock_line_mapping = {}
        self.stock_colour_mapping = {}
        self.number_of_lines = 0
        
        super().__init__(*args, **kwargs)
        
    # Creating the line text 
    def create_line(self, value, colour):
   
        value_str = f'{value:,.2f}'
        new_line = f"<span style='color:{colour};'>{value_str}</span>"
        
        return new_line
    
    # Adding a label
    def add_stock_price_label(self, stock, value, colour):
        
        new_line = self.create_line(value, colour)
        
        if hasattr(self, "HtmlText"):
            updated_html_text = self.HtmlText + "<br>" + new_line       # Appends a new line if the text exists.
        else:
            updated_html_text = new_line
      
        self.HtmlText = updated_html_text
        self.setHtml(updated_html_text)      # updates the text
        
        # Updates corresponding mapping values
        self.stock_line_mapping[stock] = self.number_of_lines
        self.stock_colour_mapping[stock] = colour
        self.number_of_lines += 1

            
    def remove_stock(self, stock):
        """
        We find the index that is being removed, split the Html text into a list, remove that str and attach the list again with line breaks 
        """
        line_to_remove = self.stock_line_mapping[stock]
        lines = self.HtmlText.split('<br>')

        del lines[line_to_remove]               # The index value.

        new_line =  '<br>'.join(lines)

        self.setHtml(new_line)        # set new text

        
        # Since the lines after the removed line is moved up, we must update the mappings to correspond to the correct line index.

        for stock_to_move, value in self.stock_line_mapping.copy().items():
            if value > line_to_remove:
                
                self.stock_line_mapping[stock_to_move] -= 1
        del self.stock_line_mapping[stock]

        self.number_of_lines -= 1
        

    def update_value(self, stock, new_value):
        
        # Add new line plot
        line_to_update = self.stock_line_mapping[stock]
      
        lines = self.HtmlText.split("<br>")
       
        colour = self.stock_colour_mapping[stock]
        
        new_line = self.create_line(new_value, colour)
       
        
        lines[line_to_update] = new_line

        updated_html = '<br>'.join(lines)
        

        self.HtmlText = updated_html

        self.setHtml(updated_html)

app = QApplication([])

win = pg.GraphicsLayoutWidget(show=True, title="Random Walk with TextItem")
win.resize(800, 600)
plot = win.addPlot(title="Random Walk")

curve = plot.plot(pen='y')

text_item = CustomTextItem(color='r', anchor=(0.5, 0.5), fill=(0, 0, 0, 150))
plot.addItem(text_item)

x = np.arange(100)
y = np.cumsum(np.random.randn(100))

first_creating = True 
counter = 0
sub1_creating = True
sub2_creating = True

def update():
    
    global x, y, first_creating, sub1_creating, sub2_creating, counter
    
    y = np.roll(y, -1)
    y[-1] = y[-2] + np.random.randn()
    
    sub1_value = np.random.rand()
    sub2_value = np.random.rand()
    curve.setData(x, y)
    
    last_x = x[-1]
    last_y = y[-1]
    
    
    """
    Initially create the main walk stock textItem and if it's created, call update_value() method
    
    """
    if first_creating:
        text_item.add_stock_price_label('main', last_y, 'red')
        first_creating=False
    else:
        text_item.update_value('main', last_y)
    
    
    """
    Between 5 to 10 iterations, create the sub TextItem, then after 10 iterations remove the item.  
    """
    
    if 10 > counter > 5:
        if sub1_creating:
            text_item.add_stock_price_label('sub1', sub1_value, 'white')
            sub1_creating = False
        else:
            text_item.update_value('sub1', sub1_value)
            
    
    if counter == 10:
        text_item.remove_stock('sub1')
    
    
    if 14 > counter > 7:
        if sub2_creating:
            text_item.add_stock_price_label('sub2', sub2_value, 'green')
            sub2_creating = False
        else:
            text_item.update_value('sub2', sub2_value)        
    
    if counter == 14:
        text_item.remove_stock('sub2')

    
    
    counter+=1
    
    text_item.setPos(last_x, last_y)

timer = QTimer()
timer.timeout.connect(update)
timer.start(1000)

if __name__ == '__main__':
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        sys.exit(app.exec_())

在更新文本项时遇到的问题源于如何替换 HTML 行。没有用包含更新值的新行替换整个行,而是仅替换了该行的一部分,从而留下了旧值的痕迹。

这是修复后的代码:

import sys
import numpy as np
import pyqtgraph as pg
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QTimer

class CustomTextItem(pg.TextItem):

    def __init__(self, *args, **kwargs):
        """


        self.stock_line_mapping to find the correct line in the html text that corresponds to the stock of the text 
        self.stock_colour_mapping to find the correct colour in the html text that corresponds to the stock of the text 
        self.number_of_lines how many lines of text is present

        """
        self.stock_line_mapping = {}
        self.stock_colour_mapping = {}
        self.number_of_lines = 0

        super().__init__(*args, **kwargs)

    # Creating the line text 
    def create_line(self, value, colour):

        value_str = f'{value:,.2f}'
        new_line = f"<span style='color:{colour};'>{value_str}</span>"

        return new_line

    # Adding a label
    def add_stock_price_label(self, stock, value, colour):

        new_line = self.create_line(value, colour)

        if hasattr(self, "HtmlText"):
            updated_html_text = self.HtmlText + "<br>" + new_line       # Appends a new line if the text exists.
        else:
            updated_html_text = new_line

        self.HtmlText = updated_html_text
        self.setHtml(updated_html_text)      # updates the text

        # Updates corresponding mapping values
        self.stock_line_mapping[stock] = self.number_of_lines
        self.stock_colour_mapping[stock] = colour
        self.number_of_lines += 1


    def remove_stock(self, stock):
        """
        We find the index that is being removed, split the Html text into a list, remove that str and attach the list again with line breaks 
        """
        line_to_remove = self.stock_line_mapping[stock]
        lines = self.HtmlText.split("<br>")

        del lines[line_to_remove]               # The index value.

        new_line =  "<br>".join(lines)

        self.setHtml(new_line)        # set new text


        # Since the lines after the removed line is moved up, we must update the mappings to correspond to the correct line index.

        for stock_to_move, value in self.stock_line_mapping.copy().items():
            if value > line_to_remove:

                self.stock_line_mapping[stock_to_move] -= 1
        del self.stock_line_mapping[stock]

        self.number_of_lines -= 1


    def update_value(self, stock, new_value):

        # Add new line plot
        line_to_update = self.stock_line_mapping[stock]

        lines = self.HtmlText.split("<br>")

        colour = self.stock_colour_mapping[stock]

        new_line = self.create_line(new_value, colour)

        # Update the entire line
        lines[line_to_update] = new_line

        updated_html = "<br>".join(lines)

        self.HtmlText = updated_html

        self.setHtml(updated_html)

app = QApplication([])

win = pg.GraphicsLayoutWidget(show=True, title="Random Walk with TextItem")
win.resize(800, 600)
plot = win.addPlot(title="Random Walk")

curve = plot.plot(pen='y')

text_item = CustomTextItem(color='r', anchor=(0.5, 0.5), fill=(0, 0, 0, 150))
plot.addItem(text_item)

x = np.arange(100)
y = np.cumsum(np.random.randn(100))

first_creating = True 
counter = 0
sub1_creating = True
sub2_creating = True

def update():
    global x, y, first_creating, sub1_creating, sub2_creating, counter

    y = np.roll(y, -1)
    y[-1] = y[-2] + np.random.randn()

    sub1_value = np.random.rand()
    sub2_value = np.random.rand()
    curve.setData(x, y)

    last_x = x[-1]
    last_y = y[-1]


    """
    Initially create the main walk stock textItem and if it's created, call update_value() method

    """
    if first_creating:
        text_item.add_stock_price_label('main', last_y, 'red')
        first_creating=False
    else:
        text_item.update_value('main', last_y)


    """
    Between 5 to 10 iterations, create the sub TextItem, then after 10 iterations remove the item.  
    """

    if 10 > counter > 5:
        if sub1_creating:
            text_item.add_stock_price_label('sub1', sub1_value, 'white')
            sub1_creating = False
        else:
            text_item.update_value('sub1', sub1_value)


    if counter == 10:
        text_item.remove_stock('sub1')


    if 14 > counter > 7:
        if sub2_creating:
            text_item.add_stock_price_label('sub2', sub2_value, 'green')
            sub2_creating = False
        else:
            text_item.update_value('sub2', sub2_value)        

    if counter == 14:
        text_item.remove_stock('sub2')



    counter+=1

    text_item.setPos(last_x, last_y)

timer = QTimer()
timer.timeout.connect(update)
timer.start(1000)

if __name__ == '__main__':
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        sys.exit(app.exec_())

通过用包含新值的完整行替换整个行,将确保旧文本被完全删除,从而解决问题并正确更新文本项。

标签:python,pyqt,pyqt5,pyqtgraph
From: 79017551

相关文章

  • 头歌实践教学平台 Python程序设计 实训答案(三)
    第七阶段文件实验一文本文件的读取第1关:学习-Python文件之文本文件的读取任务描述本关任务:使用open函数以只写的方式打开文件,打印文件的打开方式。相关知识为了完成本关任务,你需要掌握:文本文件;open函数及其参数;文件打开模式;文件对象常用属性;关闭文件close......
  • python如何实现日期加减
    首先通过importdatetime,导入日期处理库。然后把日期转化成datetime标准格式,使用datetime.datetime.strptime()方法将字符串格式的时间转化为标准格式。其中"%Y/%m/%d%H:%M:%S"为time字符串的时间格式:Y为年,m为月,d为天,H为小时,M为分钟,S为秒。如果我们要加的时间是天......
  • Python实现图形学光照和着色的Gouraud着色算法
    目录使用Python实现图形学光照和着色的Gouraud着色算法引言1.Gouraud着色算法概述1.1算法原理2.Python实现Gouraud着色算法2.1向量类2.2光源类2.3材质类2.4Gouraud着色器类2.5使用示例3.实例分析4.Gouraud着色算法的优缺点4.1优点4.2缺点5.改进方向6.应......
  • Python实现Phong着色模型算法
    目录使用Python实现Phong着色模型算法引言Phong着色模型的基本原理1.模型组成2.公式Phong着色模型的Python实现1.向量类的实现2.光源类的实现3.材质类的实现4.Phong着色器类的实现整体实现总结使用Python实现Phong着色模型算法引言在计算机图形学中,光照和......
  • 头歌实践教学平台 Python程序设计实训答案(二)
    第四阶段组合数据类型实验一列表的基本操作第1关:列表增删改:客人名单的变化任务描述列表是由按一定顺序排列的元素组成,其中的元素根据需要可能会发生变化。其中,列表元素的添加、删除或修改等是最常见的操作。下面以一则请客的故事来说明列表元素操作的应用场景。有个人邀......
  • 1、A+B(python语法格式,模块,主模块等)
    总结:python有许多模块,通过import引入模块,或者使用from从模块导入函数#导入math模块importmath#使用模块中的定义的变量或者函数的语法格式为:模块.变量/函数print(math.sqrt(25))#使用math模块中的sqrt函数,表示开平方根#从math模块中导入sqrtfrommathimpor......
  • 【Python学习笔记】字符串
    目录1.定义字符串2.基本操作2.1索引:2.2访问单个字符:2.3访问范围内字符:2.4单个字符编码3.转义符4.运算符5.格式化6.常用字符串函数6.1查找类函数6.2分割类函数6.3字符串连接方法6.4大小写字符转换方法6.5替换方法6.6删除字符串两端、右端或左端连续空白字符......
  • vscode 远程 切换python 虚拟环境
    在VSCode中远程切换Python虚拟环境是一个涉及多个步骤的过程,包括安装必要的扩展、连接到远程服务器、创建或激活虚拟环境,并在VSCode中选择相应的Python解释器。以下是一个详细的步骤指南,包括代码示例,旨在帮助我们完成这一过程。1.Vscode远程切换Python虚拟环境的步骤1.1步骤1:......
  • 常见算法——自相关的含义及Python、C实现
    常见算法——自相关的含义及C实现一、概念1.自相关概念2.滞后期示例说明:二、自相关的计算步骤:1.确定滞后期(Lag):2.计算平均值:3.计算自相关:三、示例Python自相关计算1.代码2.运行结果四、C语言实现自相关算法1.代码2.运行结果:3.优化4.检测规律波动一、概念1.自相关......
  • python中多维数组的cumsum的逆
    我想知道如何在Python中对多维数组进行累积和的逆运算。例如,我们可以通过PMy获得给定二维数组的累积数组T问题是,我如何从importnumpyasnpT=np.array([[1,3,2],[5,5,6],[1,8,3]])P=np.cumsum(np.cumsum(T,axis=0),axis=1)print(P)#Pisthe......