0

How can I set a new value to a label in tkinter? I have this code, but it's only show a blank window Sorry for my english and, please, if you can, explain. (I'm new to programming) Thank you for your attention!

import os, time, tkinter, urllib
from tkinter import *
from urllib.request import *
from urllib.error import *

class App:
    def __init__(self, master):
        v = StringVar()
        start_time = time.time()
        frame = Frame(master)
        frame.pack()
        self.label = Label(frame, textvariable=v).pack()
        if self.internet_on() == 1:
            v.set = "Internet is online"
            start_time = time.time()
        else:
            v.set = "Internet is offline!  Downtime: " + str(time.time() - start_time)


    def internet_on(self):
        try:
            response=urllib.request.urlopen('http://www.google.com.br',timeout=1)
            return True
        except urllib.error.URLError as err: pass
        return False            
top = tkinter.Tk()
app = App(top)

top.mainloop()
Anand S Kumar
  • 88,551
  • 18
  • 188
  • 176

2 Answers2

3

v.set is a method, you are not supposed to write over it as -

v.set = "Internet is online"

You are supposed to call it and pass the string you want to write as argument -

v.set("Internet is online")

And

v.set("Internet is offline!  Downtime: " + str(time.time() - start_time))

As noted in the comments, you can also directly set the text value for the label , and then use label.config() to change the text. Example -

import os, time, tkinter, urllib
from tkinter import *
from urllib.request import *
from urllib.error import *

class App:
    def __init__(self, master):
        start_time = time.time()
        frame = Frame(master)
        frame.pack()
        if self.internet_on() == 1:
            self.label = Label(frame, text="Internet is online")
            self.label.pack()
            start_time = time.time()
        else:
            self.label = Label(frame, text="Internet is offline!  Downtime: " + str(time.time() - start_time))
            self.label.pack()


    def internet_on(self):
        try:
            response=urllib.request.urlopen('http://www.google.com.br',timeout=1)
            return True
        except urllib.error.URLError as err: pass
        return False            
top = tkinter.Tk()
app = App(top)

top.mainloop()

The best way to solve your requirement -

In 'internet_on', periodically checking the internet status (change the text in the label). I already tried to use while with no sucess.

Would be to use .after() method of Tk() specifying a time in milliseconds (maye something like 5000 milliseconds or so , you can decide this) and specifying the iternet_on method as second argument and then using the internet_on method update the label. Example -

import os, time, tkinter, urllib
from tkinter import *
from urllib.request import *
from urllib.error import *

class App:
    def __init__(self, master):
        start_time = time.time()
        self.master = master
        self.frame = Frame(master)
        self.frame.pack()
        self.label = Label(self.frame, text="")
        self.label.pack()
        self.start_time = time.time()


    def internet_on(self):
        try:
            response=urllib.request.urlopen('http://www.google.com.br',timeout=1)
            self.label.config(text="Internet is online")
        except urllib.error.URLError as err:
            self.label.config(text="Internet is offline!  Downtime: " + str(time.time() - self.start_time))
        self.master.after(5000,self.internet_on)          
top = tkinter.Tk()
app = App(top)
top.after(5000,app.internet_on)
top.mainloop()
Anand S Kumar
  • 88,551
  • 18
  • 188
  • 176
  • 3
    You don't need to use StringVar. – nbro Aug 21 '15 at 01:42
  • Sorry, you don't need to do what? – Anand S Kumar Aug 21 '15 at 01:44
  • Not for that particular usecase, but I am guessing he is learning to use tkinter, and for a bit more complex usecase (like maybe checking the same thing multiple times ad updating the label ) you would need a `StringVar()` , correct me if I am wrong, would there be a way to do that usecase (update the label later) without using StringVar? – Anand S Kumar Aug 21 '15 at 01:46
  • 3
    You can update the label's (and in general widget's) _logical_ attributes using the `config` method (or its alias `configure`). `StringVar` is only necessary when you want to synchronise different widgets to have the same content, in this case the same text, IMO. – nbro Aug 21 '15 at 01:48
  • Ok, added an example for that as well. Personally , I think it would be cleaner to use `StringVar()` . – Anand S Kumar Aug 21 '15 at 01:51
  • 2
    If there's no need for a `StringVar`, why create one? Also why not create the `Label` _after_ calling `internet_on()` and just putting the right `text` into it in the first place? Lastly, the `urllib.request.urlopen()` call is messed up in your current answer. – martineau Aug 21 '15 at 01:55
  • Thank you sir!! . But it still not updating. What can I do to make it refresh the label (change value of the label during runtime)? – Bruno Soares Aug 21 '15 at 02:12
  • When do you want to refresh the label? – Anand S Kumar Aug 21 '15 at 02:17
  • In 'internet_on', periodically checking the internet status (change the text in the label). I already tried to use while with no sucess. – Bruno Soares Aug 21 '15 at 02:20
  • Hmm , give me some time I will update it. In the meantime you can check out .after method , which is what you should be using for your case . – Anand S Kumar Aug 21 '15 at 02:43
  • You're only checking once, in your `__init__` method. To check periodically, you can use the tkinter `after` method. http://stackoverflow.com/questions/25753632/tkinter-how-to-use-after-method – saulspatz Aug 21 '15 at 02:45
  • Not update method , after method . Check out the link given in the above comment by saulspatz – Anand S Kumar Aug 21 '15 at 02:54
  • Its not exactly similar, and theres not much difference that can be brought here. Anyway I didn't look at your solution at all, just noticed the similarity when you commented, – Anand S Kumar Aug 21 '15 at 09:24
  • Thank you, It worked flawness. But I have a question: the .after() invokes .mainloop() or the .after() just invoke that same come over periodically? ( I noticed that .mainloop() "freezes" the code in it invoke) – Bruno Soares Aug 21 '15 at 16:05
  • They are different things, `.after()` invokes the function after that many milliseconds, the invocation itself is handled by `root.mainloop()` . – Anand S Kumar Aug 21 '15 at 16:07
  • mainloop() goes into an infinite loop where it keeps listening for events from the gui. – Anand S Kumar Aug 21 '15 at 16:07
  • Why a widget text change do not call a event? (if it keeps listening) – Bruno Soares Aug 21 '15 at 16:12
  • You can configure to listen to events, but unless you configure in your code to listen to events, tkinter cannot magically deduce which method/function you want to call when a particular event is raised. – Anand S Kumar Aug 21 '15 at 16:14
  • @AnandSKumar Sorry for my retard question. Thank you so much sir!! – Bruno Soares Aug 21 '15 at 16:19
  • Its not retarded at all :-) , sorry If I came off rude. – Anand S Kumar Aug 21 '15 at 16:21
0

The simplest method is to do the updating in the method forgetting returning booleans and using root.after:

from tkinter import *
import  urllib.request
import urllib.error

class App(Frame):
    def __init__(self, master):
        Frame.__init__(self, master)
        self.start_time = time.time()
        self.label = Label(root, text="Starting.....")
        self.label.pack()
        self.internet_on()

    def internet_on(self):
        try:
            urllib.request.urlopen('http://www.google.com.br', timeout=1)
            self.label.config(text="Internet is online")
            self.start_time = time.time()
        except urllib.error.URLError:
            self.label.config(text="Internet is offline!  Downtime: " + str(time.time() - self.start_time))
        root.after(1000, self.internet_on)

root = tkinter.Tk()
app = App(root)
app.pack()
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321