refresh automatically text wiget tkinter

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • atlass218
    New Member
    • Dec 2018
    • 1

    refresh automatically text wiget tkinter

    Hi; I created an application that is based on the introduction of data stored in txt files. the content of these files is displayed in text widget
    my problem is that I can not get the automatic refresh of the text widget display

    the code in python 3.6, and it cutted into several parts :

    Code:
    from tkinter import *
    from tkinter.ttk import Notebook
    import tkinter.ttk as ttk
    import time
    #window
    root=Tk()
    root.geometry('450x350')
    root.title('test')
    #variables
    ent_releves1=StringVar()
    ent_releves2=StringVar()
    part of code for functions

    Code:
    #Functions:
    def archiver():
         
        archive_monitoring={"date" : time.strftime('%d/%m/%y', time.localtime()),  
                      "releves_mesure1": ent_releves1.get(),
                      "releves_mesure2": ent_releves2.get(),                          }
         
        if (ent_releves1.get() !="" ) :
            mon_fichier1 = open("save1/monitor1.txt", "r")
            text1 = mon_fichier1.read()
            mon_fichier1.close()                       
            textInsert1=str(archive_monitoring["date"])+"\t" +str(archive_monitoring["releves_mesure1"])+"\n"
            fileW1 = open("save1/monitor1.txt", "w")
            fileW1.write(textInsert1 + text1)
            fileW1.close()
         
        if (ent_releves2.get() !="" ) :
            mon_fichier2 = open("save1/monitor2.txt", "r")
            text2 = mon_fichier2.read()
            mon_fichier2.close()                       
            textInsert2=str(archive_monitoring["date"])+"\t" +str(archive_monitoring["releves_mesure2"])+"\n"
            fileW2 = open("save1/monitor2.txt", "w")
            fileW2.write(textInsert2 + text2)
            fileW2.close()
    Code:
    def affichage_update ():
        with open('save1/monitor1.txt',"r") as monitor1, open('save1/monitor2.txt',"r") as monitor2:     
            s= Scrollbar(releves)
            T= Text(releves,bg='powder blue',width=450,height=350,font=('arial',14,'bold'),pady=25)   
            s.pack(side=RIGHT, fill=Y)
            T.pack(side=LEFT, fill=Y)
            s.config(command=T.yview)
            T.config(yscrollcommand=s.set)        
            while True:
                line1 = monitor1.readline()
                if len(line1) == 0:
                    break
                line1 = line1.strip().split()
                line2 = monitor2.readline()
                line2 = line2.strip().split()
                T.insert(END, f'{line1[0]:15}\t {line1[1]:10}\t\t {line2[1]:10}\n')
        T.update_idletasks()
        T.after(500,affichage_update)
    code for notebook and label :

    Code:
    container=ttk.Notebook(root,width=450,height=350)
    monitoring=Frame(container,bg='powder blue')
    container.add(monitoring,text='monitor data')
    releves=Frame(container,bg='powder blue')
    container.add(releves,text='releves')
    lbf1 = LabelFrame(monitoring, text="Lecture Monitor 1",padx=10, pady=10)
    lbf1.pack(side=LEFT,padx=10, pady=10,anchor=NE)
    entry_lbf1= Entry(lbf1,textvariable=ent_releves1)
    entry_lbf1.pack(pady=5)
    lbf2 = LabelFrame(monitoring, text="Lecture Monitor 2",padx=10, pady=10)
    lbf2.pack(side=LEFT,padx=10, pady=10,anchor=NW)
    entry_lbf2= Entry(lbf2,textvariable=ent_releves2)
    entry_lbf2.pack(pady=5)
    bt_archiver=Button(monitoring,text='Archiver',command=archiver)
    bt_archiver.place(x=40,y=120)
    Code:
    generalites_top=Frame(releves,bg='powder blue',width=450)
    generalites_top.pack(side=TOP,fill=X)
    generalites_bottom=Frame(releves,bg='powder blue')
    generalites_bottom.pack(side=BOTTOM)
    head_axe_loc35L = ['Date', 'Monitor 1', 'Monitor 2']
    lb_date=Label(generalites_top,text=f'{head_axe_loc35L[0]:15}',bg='powder blue',font=('arial',12,'bold'))
    lb_date.pack(side=LEFT,padx=5,anchor=NW)
    lb_monitor1=Label(generalites_top,text=f'{head_axe_loc35L[1]:10}',bg='powder blue',font=('arial',12,'bold'))
    lb_monitor1.pack( side=LEFT)
    lb_monitor2=Label(generalites_top,text=f'{head_axe_loc35L[2]:10}',bg='powder blue',font=('arial',12,'bold'))
    lb_monitor2.pack(padx=70, side=LEFT)
    Code:
    with open('save1/monitor1.txt',"r") as monitor1, open('save1/monitor2.txt',"r") as monitor2:        
        s= Scrollbar(releves)
        T= Text(releves,bg='powder blue',width=450,height=350,font=('arial',14,'bold'),pady=25)
           
        s.pack(side=RIGHT, fill=Y)
        T.pack(side=LEFT, fill=Y)
        s.config(command=T.yview)
        T.config(yscrollcommand=s.set)        
        while True:
            line1 = monitor1.readline()
            if len(line1) == 0:
                break
            line1 = line1.strip().split()
            line2 = monitor2.readline()
            line2 = line2.strip().split()
            T.insert(END, f'{line1[0]:15}\t {line1[1]:10}\t\t {line2[1]:10}\n')
    T.update_idletasks()           
    T.after(500,affichage_update)  
    container.pack(expand=1, fill='both', padx=5, pady=5) 
    root.mainloop()
    I need help to rectify my code
    thanks for help
  • dwblas
    Recognized Expert Contributor
    • May 2008
    • 626

    #2
    Most likely the while True is hogging the processor and not letting anything else happen. Instead of a while True, call another function repeatedly, using after() to update the Text and then call itself again. The small amount of time after() waits before executing gives the processor/Tkinter time to do things like update widgets. The same for any other while True loops. Sorry, but there is too much code for me to trudge through (How come you have this problem at this stage. Has this code not been tested at all?). Will try to come up with a simple example later today, but no promises.

    Edit: this is code in my toolbox. Note how the countdown timer creates the Label and then updates it through a second function (the simple progressbar has nothing to do with your question). I would also strongly suggest that you learn classes before Tkinter as it solves some problems, like accessing variables in a called function that were created somewhere else.
    Code:
    class ProgressBar():
        def __init__(self, root):
            self.root=root
            self.root.geometry("75x50+900+100")
            tk.Button(self.root, text="Quit", bg="red", command=self.root.destroy).pack()
            self.ctr=25
            self.start_progress_bar()
            self.start_countdown()
    
        def start_progress_bar(self):
            """ create a simple progress bar widget on a canvas
            """
            self.top=tk.Toplevel(self.root, takefocus=True)
            self.top.title("Progress Bar")
            self.top.geometry("+700+200")
            self.canvas = tk.Canvas(self.top, width=261, height=60, background='lightgray')
            self.canvas.pack()
    
            self.rc1 = self.canvas.create_rectangle(24, 20, 32, 50, outline='white', \
                                          fill='blue')
            self.start_x=20
            self.end_x=235
            self.this_x=self.start_x
            self.one_25th = (self.end_x-self.start_x)/25.0
            rc2 = self.canvas.create_rectangle(self.start_x, 20, self.end_x, 50,
                                           outline='blue', fill='lightblue')
            self.rc1 = self.canvas.create_rectangle(self.start_x, 20, self.start_x+7, 50,
                                           outline='white', fill='blue')
    
            self.update_scale()
    
        def start_countdown(self):
            """ a separate process in a separate GUI
            """
            top2=tk.Toplevel(self.root, bg="lightyellow")
            top2.geometry("50x25")
            self.label_ctr = tk.IntVar()
            self.label_ctr.set(self.ctr)
            tk.Label(top2, textvariable=self.label_ctr, width=10,
                     font=("Verdans", 15)).pack()
            if self.ctr > 0:
                self.update()
            else:
                self.top2.destroy()
    
        def update(self):
            if self.ctr > 0:
                self.label_ctr.set(self.ctr)
                self.ctr -= 1
                self.root.after(750, self.update)
            else:
                ## sleep for one second to allow any remaining after() to execute
                ## can also use self.root.after_cancel(id)
                self.root.after(1000, self.root.destroy)
    
        def update_scale(self):
            self.canvas.move(self.rc1, self.one_25th, 0)
            self.canvas.update()
            self.this_x += self.one_25th
            ## reverse direction at either end
            if (self.this_x >= self.end_x-12) or self.this_x <= self.start_x+7:
                self.one_25th *= -1
    
            ## only call after() while the countdown is running (self.ctr > 0)
            ## to avoid a dangling after() when the program terminates
            if self.ctr > 0:
                self.canvas.after(200, self.update_scale)
    
    root = tk.Tk()
    
    PB=ProgressBar(root)
    root.mainloop()

    Comment

    Working...