首页 > 解决方案 > 在 Tkinter 中更新文本小部件中的值

问题描述

我需要在不关闭该窗口的情况下在 10 秒后更新同一 Tkinter 窗口中的一些其他数据的值。我试过使用afterTkinter 的方法,但它不适合我的目的。depth_chart是一个需要在此窗口中显示的具有 3 列和多行的数组。

from tkinter import *
root = Tk()
root.title("Depth Ladder")

height = len(depth_chart)
width = len(depth_chart[0])
Label(root, text = "Bid Quantity").grid(row = 0, column = 0)
Label(root, text = "Price").grid(row = 0, column = 1)
Label(root, text = "Ask Quantity").grid(row = 0, column = 2)
for i in range(height): #Rows
    for j in range(width): #Columns
        a= str(depth_chart[i][j])
        b = Text(root,height =1)
        if a != "None":
            b.insert(INSERT,a)
        if j ==0:
            b.config(bg="green",fg = "white",relief = RIDGE,width =8)
        elif j==1:
            b.config(background="black",fg = "white",relief = RIDGE,width =12)
        elif j ==2:
            b.config(background="red",fg = "white",relief = RIDGE,width =8)
        b.grid(row=i+1, column=j)
root.mainloop()

标签: pythontkinter

解决方案


您可以首先使用空小部件创建网格Text并将它们保留在 2D 列表中。

稍后您可以运行从小部件中删除旧数据Text并放入新数据的功能。最后它应该after()在 10 秒后再次运行。

问题可以生成获取新数据的代码,depth_chart但您没有显示这部分,所以我模拟更改depth_chart


在此示例中,我创建随机数据并每 1 秒更新一次。

import tkinter as tk # PEP8: `import *` is not preferred
import random  # simulate changes in data

# --- functions ---

def fill_text():
    global depth_chart

    for y, row in enumerate(depth_chart):
        for x, item in enumerate(row):
            # remove previous text
            all_text[y][x].delete('0.1', 'end')
            # add new text
            if item is not None:
                all_text[y][x].insert('insert', item)

    # simulate changes in data                
    depth_chart = [[random.randint(0, 10) for x in range(3)] for y in range(10)]

    # fill it again after 1s (1000ms)
    root.after(1000, fill_text)
    
# --- main ---

# simulate changes in data
depth_chart = [[random.randint(0, 10) for x in range(3)] for y in range(10)]

root = tk.Tk()
root.title("Depth Ladder")

tk.Label(root, text="Bid Quantity").grid(row=0, column=0)  # PEP8: without spaces around `=`
tk.Label(root, text="Price").grid(row=0, column=1)
tk.Label(root, text="Ask Quantity").grid(row=0, column=2)

# create grid with empty widgets `Text` and remember them on 2D list
all_text = []
for y, row in enumerate(depth_chart, 1): 
    row_text = []
    for x, item in enumerate(row):
        text = tk.Text(root, height=1)
        text.grid(row=y, column=x)
        
        if x == 0:
            text.config(bg="green", fg="white", relief='ridge', width=8)
        elif x == 1:
            text.config(bg="black", fg="white", relief='ridge', width=12)
        elif x == 2:
            text.config(bg="red", fg="white", relief='ridge', width=8)

        row_text.append(text)

    all_text.append(row_text)
        
# fill it first time        
fill_text()

root.mainloop()

编辑:

如果您每 10 秒有不同的行数,depth_chart那么从网格中删除所有行并再次创建新小部件会更容易Text- 然后您可以在Text创建时直接添加值。

它有一个问题 -当所有小部件都被移除时它会闪烁。

import tkinter as tk # PEP8: `import *` is not preferred
import random  # simulate changes in data

# --- functions ---

def fill_text():
    global depth_chart
    global all_text

    # simulate changes in data                
    number_of_rows = random.randint(5, 20)
    depth_chart = [[random.randint(0, 10) for x in range(3)] for y in range(number_of_rows)]
    
    # delete old text widgets
    for row in all_text: 
        for item in row:
            item.destroy()
            
    # clear list
    all_text = []
    
    # create grid with widgets `Text` and remember them on 2D list
    for y, row in enumerate(depth_chart, 1): 
        row_text = []
        for x, item in enumerate(row):
            text = tk.Text(root, height=1)
            text.grid(row=y, column=x)
            
            if x == 0:
                text.config(bg="green", fg="white", relief='ridge', width=8)
            elif x == 1:
                text.config(bg="black", fg="white", relief='ridge', width=12)
            elif x == 2:
                text.config(bg="red", fg="white", relief='ridge', width=8)

            if item is not None:
                text.insert('insert', item)
    
            row_text.append(text)
    
        all_text.append(row_text)

    # fill it again after 1s (1000ms)
    root.after(1000, fill_text)
    
# --- main ---

# place for all text widgets
all_text = []

root = tk.Tk()
root.title("Depth Ladder")

tk.Label(root, text="Bid Quantity").grid(row=0, column=0)  # PEP8: without spaces around `=`
tk.Label(root, text="Price").grid(row=0, column=1)
tk.Label(root, text="Ask Quantity").grid(row=0, column=2)
        
# fill it first time        
fill_text()

root.mainloop()

要解决闪烁问题,需要更复杂的代码来删除或添加只需要的行。

import tkinter as tk # PEP8: `import *` is not preferred
import random  # simulate changes in data

# --- functions ---

def fill_text():
    global depth_chart
    global all_text

    # simulate changes in data                
    number_of_rows = random.randint(5, 20)
    depth_chart = [[random.randint(0, 10) for x in range(3)] for y in range(number_of_rows)]

    # calculate how many rows add or delete        
    len_chart = len(depth_chart)
    len_all   = len(all_text)
    diff = len_chart - len_all
    
    #print(number_of_rows, diff)
    
    if diff < 0:
        # delete widgets
        for row in all_text[diff:]: 
            for item in row:
                item.destroy()
        all_text = all_text[:diff]
    elif diff > 0:
        # add widgets
        for y in range(len_all+1, len_chart+1):
            
            text1 = tk.Text(root, height=1)
            text1.grid(row=y, column=0)
            text1.config(bg="green", fg="white", relief='ridge', width=8)

            text2 = tk.Text(root, height=1)
            text2.grid(row=y, column=1)
            text2.config(bg="black", fg="white", relief='ridge', width=12)

            text3 = tk.Text(root, height=1)
            text3.grid(row=y, column=2)
            text3.config(bg="red", fg="white", relief='ridge', width=8)

            all_text.append([text1, text2, text3])
                
    # put values in `Text`            
    for y, row in enumerate(depth_chart):
        for x, item in enumerate(row):
            # remove previous text
            all_text[y][x].delete('0.1', 'end')
            # add new text
            if item is not None:
                all_text[y][x].insert('insert', item)

    # fill it again after 1s (1000ms)
    root.after(1000, fill_text)
    
# --- main ---

# place for all text widgets
all_text = []

root = tk.Tk()
root.title("Depth Ladder")

tk.Label(root, text="Bid Quantity").grid(row=0, column=0)  # PEP8: without spaces around `=`
tk.Label(root, text="Price").grid(row=0, column=1)
tk.Label(root, text="Ask Quantity").grid(row=0, column=2)
        
# fill it first time        
fill_text()

root.mainloop()

推荐阅读