Обновление виджета в подокне с данными в реальном времени в Python tkinter - PullRequest
0 голосов
/ 21 сентября 2018

Я пытался использовать after / time.sleep для обновления древовидного списка, но он не работает с mainloop.

Мои вопросы:

  • Как я могу обновить виджет в виде дерева с данными в реальном времени?
  • И есть ли способ, которым я могу изменить всех потомков дерева одновременно?(Я не хочу удалять всех детей и вставлять снова)

Сценарий 1:

class mainwindow(tk.Tk):
    #Initalize main window
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

       #use to shift frames
       ....
 if __name__ == "__main__":
    ...
    app = mainwindow()
    app.geometry("1920x1080")
    app.mainloop()

Сценарий 2:

class Page_one(tk.Frame):
    def __init__(self, parent, controller):
        mainframe=tk.Frame.__init__(self, parent)
        self.controller = controller

        #treeview widget attached to page_one
        tree1=Treeviews(...)
        tree1.place(x=880,y=25)

#Question1: How can I update the treeview widget with real-time data? 
#Question2: is there a way that I can change all treeview children simuteniously? (I dont want to delete all children and insert again)

Мой вопросКто-нибудь может показать мне структуру, которую я мог бы использовать для обновления виджетов во втором сценарии.

1 Ответ

0 голосов
/ 21 сентября 2018

Вы можете изменить виджет в виде дерева с помощью метода item:

tree.item(<item id>, text='new text', values=(...))

Идентификатор элемента возвращается при создании элемента.И вы можете изменить все дочерние элементы древовидной структуры, поместив приведенный выше код в цикл for:

for item in tree.get_children(<parent>):
    tree.item(item, text='new text', values=(...))

tree.get_children(<parent>) возвращает дочерние элементы элемента ('' для корня дерева).

Из вашего вопроса я понимаю, что у вас есть какой-то отдельный процесс, который генерирует данные, и вы хотите периодически обновлять содержимое древовидной структуры новыми генерируемыми данными.Использование time.sleep заморозит основной цикл, поэтому вы должны использовать метод after tkinter: tree.after(<time in ms>, callback, *args) будет ждать указанное время и затем выполнит callback(*args).Если вам нужен периодический обратный вызов, хитрость заключается в том, чтобы снова вызвать after внутри callback, например:

def callback(x, y):
    # do something with x and y ...
    tree.after(2000, callback, x, y)

Так что, как только вы запустите callback(0, 2), он будет выполняться каждые 2 с.

Вот пример с деревом:

import tkinter as tk
from tkinter import ttk

def update_item(item):
    val = int(tree.item(item, 'value')[0])
    tree.item(item, values=(val + 1,))
    root.after(1000, update_item, item)

def update_all_items():
    for item in tree.get_children():
        tree.item(item, values=(0,))

root = tk.Tk()
tree = ttk.Treeview(root, columns=('value'))
tree.heading('value', text='Value')

for i in range(5):
    tree.insert('', 'end', 'item%i' % i, text='item %i' % i, values=(i,))

update_item('item0')

tree.pack()
ttk.Button(root, text='Update', command=update_all_items).pack()

root.mainloop()
...