How to Infinitely Update Labels with while loop tk

2019-08-21 08:44发布

问题:

Hi I have some simple code here. https://pastebin.com/97uuqKQD

I would simply like to add something like this, to the button function, so while the root window is open the datetime and exrates are constantly regotten from the xe website and displayed.

amount = '1'

def continuousUpdate():
    while amount == '0':
        results()

def results():
    #Get xe data put to labels etc here

btnConvert = tk.Button(root, text="Get Exchange Rates",command=continuousUpdate).place(x=5,y=102)

Once I input the two exrates and they then display on there respective labels I would like the program to continuously grab the data from xe over and over again.

Like this code here which runs in IPython no problems,

import requests
from bs4 import BeautifulSoup
from datetime import datetime

amount = '1'

while amount != '0':
    t = datetime.utcnow()  
    url1  = "http://www.xe.com/currencyconverter/convert/" + "?Amount=" + amount + "&From=" + cur1 + "&To=" + cur2
    url2 = "http://www.xe.com/currencyconverter/convert/" + "?Amount=" + amount + "&From=" + cur2 + "&To=" + cur1
    #url = "http://www.xe.com/currencycharts/" + "?from=" + cur1 + "&to=" + cur2               
    html_code1 = requests.get(url1).text
    html_code2 = requests.get(url2).text

    soup1 = BeautifulSoup(html_code1, 'html.parser')
    soup2 = BeautifulSoup(html_code2, 'html.parser')

    i = i + 1

    rate1 = soup1.find('span', {'class', 'uccResultAmount'})
    rate2 = soup2.find('span', {'class', 'uccResultAmount'})

    print ('#',i, t,'\n', cur1,'-',cur2, rate1.contents[0], cur2,'-',cur1, rate2.contents[0], '\n')

I thought I would just be able to throw the entire results function into a while loop function then simply call that function but no luck any help would be appreciated.???

回答1:

Put this at the end of your results function without the while loop:

after_id = root.after(milliseconds,results) 

This way it just keeps running itself after that time you specified. And this code will cancel it.

root.after_cancel(after_id)


Answering your other question in the comments:
To make a cancel button make sure after_id is global. Also if the time you specify is very low (very fast recall) it might restart again before you can cancel it. So to be safe better make a global boolean and put .after in an if boolean==True. And you can set that boolean to False whenever you hit cancel button or to True whenever you hit the start button, here's how you can do it:

# button_call default will be True so if you click on the button
# this will be True (no need to pass var through). You can use this to set 
# your restart boolean to True
def func(button_call=True): 
    global restart
    global after_id
    if button_call:
        restart = True
    if restart:
        after_id = root.after(ms,lambda: func(button_call=False) )
        # This way you know that func was called by after and not the button

Now you can put this in your cancel button function:

def cancel():
    global restart
    global after_id
    root.after_cancel(after_id)
    restart = False

Let me know if this works (haven't tested it myself).