Python Forum
[Tkinter] Update value in Entry widget
Thread Rating:
  • 2 Vote(s) - 2.5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] Update value in Entry widget
#1
I'm very new to tkinter. How do I get a value to display every time it changes? The code below only shows the last entry in the Entry widget, but print shows all the values (python 3.6.0)

from tkinter import *
def start():
    for n in range(1000000):
        if n%100000 == 0:
            v.set(str(n))
def makeWindow () :
    global v
    win = Tk()
    frame1 = Frame(win)
    frame1.pack()
    Label(frame1, text="Number").grid(row=0, column=0, sticky=W)
    v = StringVar()
    m = Label(frame1, textvariable=v)
    m.grid(row=0, column=1, sticky=W)
    frame2 = Frame(win)
    frame2.pack()
    b1 = Button(frame2,text=" Start  ",command=start)
    b1.pack(side=LEFT)
    return win
win = makeWindow()
win.mainloop()
Reply
#2
it doesnt look like the problem is with GUI, it looks like your problem is with your programming. 

Quote:
def start():
    for n in range(1000000):
        if n%100000 == 0:
            v.set(str(n))

Every time you hit the button you execute start(). This function sets the string var (v) to every 100K (0-900000) in a split second. The last value 900000 gets seen as the label because its the last iteration and the completion of the function. Thus you will not see any other number in the label like you would with the print function...assuming this is what you wanted to do?

EDIT:
Do you mean something like this? I would suggest to use classes instead of global keywords. 
from tkinter import *

class Values:
    def __init__(self):
        self.vals = []
        self.index = 0
        self.assign()
    def assign(self):
        '''get our values'''
        for n in range(1000000):
            if n%100000 == 0:
                self.vals.append(n)
    def reset(self):
        '''what do we do when we iterate all values? Start at 0'''
        if self.index > len(self.vals)-1: 
            self.index = 0
            
    def callback(self):
        '''execute when button gets pressed'''
        self.reset()
        v.set(self.vals[self.index])
        self.index += 1
        

win = Tk()
v = StringVar()
obj = Values()
frame1 = Frame(win)
frame1.pack()
Label(frame1, text="Number").grid(row=0, column=0, sticky=W)

m = Label(frame1, textvariable=v)
m.grid(row=0, column=1, sticky=W)
frame2 = Frame(win)
frame2.pack()
b1 = Button(frame2,text=" Start  ",command=obj.callback)
b1.pack(side=LEFT)
#win = makeWindow()
win.mainloop()
Recommended Tutorials:
Reply
#3
Hi metulburr.

Thanks for the quick reply. Your solution is not quite what I want. I have been "programming" in python for quite a few years as a means of solving some cryptographic puzzles, but without using classes. I just use python as a type of programmable calculator to manipulate text to find solutions to problems. Now I have retired I thought I would try to make my programs look a bit smarter. Some of the programs I write take days to execute, and I have been using print to show me that the program is still running and to give me an idea of how far it has progressed. I was trying to use tkinter to display the results on screen every time that a particular variable changed without me having to press the "start" button each time. The example I posted was just a simple program that I hoped would show me the count updating in the Entry box each time it changed, as it does on the console if I put a "print(n)" statement in the loop.
Reply
#4
A metulburr said you code is updating so fast the eye cannot register the changes so you only see the last one.
If you import time and changed your example code to this 
def start():
    for n in range(1000000):
        if n%100000 == 0:
            v.set(str(n))
            time.sleep(0.5)
you would see the values changing.
Reply
#5
(Mar-31-2017, 04:38 PM)Barrowman Wrote: A metulburr said you code is updating so fast the eye cannot register the changes so you only see the last one.
If you import time and changed your example code to this 
def start():
    for n in range(1000000):
        if n%100000 == 0:
            v.set(str(n))
            time.sleep(0.5)
you would see the values changing.

But because of it being tkinter you cant use time sleep on any GUI as it blocks the execution, you have to use after
Recommended Tutorials:
Reply
#6
Hi Barrowman.

Thanks for the reply. I'll have a look at the after method and see if I can get it to work.
Reply
#7
Hi dannyH

I assume you want to update the value of a Label not Entry? If you use a Label to display a changing value the following script may help you:
(Use of threading and after())
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import threading

try:
    # Tkinter for Python 2.xx
    import Tkinter as tk
    import Queue as qu
except ImportError:
    # Tkinter for Python 3.xx
    import tkinter as tk
    import queue as qu

APP_TITLE = "Update Label Display"
APP_XPOS = 100
APP_YPOS = 100
APP_WIDTH = 300
APP_HEIGHT = 200
UPDATE_TIME = 500 # Milliseconds

QUEUE_SIZE = 10
POLLING_TIME = 500   # Milliseconds

class AppThread(threading.Thread):
    
    def __init__(self, queue=None, max_number=0, modulo=0):
        self.queue = queue
        self.max_number = max_number
        self.modulo = modulo
        
        threading.Thread.__init__(self)
        self.start()

    def run(self):
        num_count = 0
        while num_count < self.max_number:
            if num_count%self.modulo == 0:
                self.update_queue(num_count)
            num_count += 1
   
    def update_queue(self, num_count):
        self.queue.put(num_count)
        self.queue.join()
    
class Application(tk.Frame):

    def __init__(self, master):
        self.master = master
        self.master.protocol("WM_DELETE_WINDOW", self.close)
        tk.Frame.__init__(self, master)
        
        self.max_number = 1000000
        self.modulo = 100000
        self.app_thread = None
        
        self.control_frame = tk.Frame(self)
        self.control_frame.pack(expand=True)
        
        tk.Label(self.control_frame, text="Number:").pack(fill='x', pady=(0,1))
        
        self.var = tk.StringVar()
        tk.Label(self.control_frame, relief='sunken', bg='white', width=10,
            textvariable=self.var).pack(fill='x', pady=(0,10))
        
        tk.Button(self.control_frame, text=" Start  ",
            command=self.start_thread).pack(fill='x')

        self.queue = qu.Queue(QUEUE_SIZE)
        self.queue_polling()
    
    def start_thread(self):
        if self.app_thread == None:
            self.app_thread = AppThread(
                self.queue, self.max_number, self.modulo)
        else:
            if not self.app_thread.isAlive():
                self.app_thread = AppThread(
                self.queue, self.max_number, self.modulo)
        
    def queue_polling(self):
        if self.queue.qsize():
            try:
                data = self.queue.get()
                self.var.set(str(data))
                self.queue.task_done()
            except qu.Empty:
                pass
        
        self.after(POLLING_TIME, self.queue_polling)
                
    def close(self):
        print("Application-Shutdown")
        self.app_thread.join()
        self.master.destroy()
    
def main():
    app_win = tk.Tk()
    app_win.title(APP_TITLE)
    app_win.geometry("+{}+{}".format(APP_XPOS, APP_YPOS))
    app_win.geometry("{}x{}".format(APP_WIDTH, APP_HEIGHT))
    
    app = Application(app_win).pack(fill='both', expand=True)
    
    app_win.mainloop()
 
 
if __name__ == '__main__':
    main()      
wuf Smile
Reply
#8
Many thanks. That is the functionality I was looking for, although the code is a bit more complicated than I am used to writing. Now that I have more free time I will investigate tkinter, classes and threading and hopefully write better python programs in the future.

The problem with the original code was not speed - I slowed it down by a factor of 100 so that it took 32 seconds to run, but still the only value that appeared in the window was the last one to be calculated.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  ValueError: could not convert string to float: '' fron Entry Widget russellm44 5 497 Mar-06-2024, 08:42 PM
Last Post: russellm44
  [Tkinter] entry widget DPaul 5 1,437 Jul-28-2023, 02:31 PM
Last Post: deanhystad
  How to instantly update the plot by getting values from a Scale widget? OLE 20 6,051 May-18-2022, 02:35 AM
Last Post: OLE
  Tkinter Exit Code based on Entry Widget Nu2Python 6 2,877 Oct-21-2021, 03:01 PM
Last Post: Nu2Python
  [Tkinter] Update variable using tkinter entry methon drSlump 6 5,095 Oct-15-2021, 08:01 AM
Last Post: drSlump
  method to add entries in multi columns entry frames in self widget sudeshna24 2 2,214 Feb-19-2021, 05:24 PM
Last Post: BashBedlam
  Entry Widget issue PA3040 16 6,657 Jan-20-2021, 02:21 PM
Last Post: pitterbrayn
  [Tkinter] password with Entry widget TAREKYANGUI 9 5,778 Sep-24-2020, 05:27 PM
Last Post: TAREKYANGUI
  [Tkinter] Get the last entry in my text widget Pedroski55 3 6,295 Jul-13-2020, 10:34 PM
Last Post: Pedroski55
  How to retreive the grid location of an Entry widget kenwatts275 7 4,478 Apr-24-2020, 11:39 PM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020