How to show data in tkinter module dynamically-Python - python

I am new to GUI creation in python using Tkinter. I found a script in stack overflow which gives a GUI in which i can i add data manually. I tried to add data dynamically thus automating the whole process using following code:
def insert_data(self):
"""
Insertion method.
"""
for l in range(10):
time.sleep(3)
print(i)
self.treeview.insert('', 'end', text="Item_"+str(self.i)+str(l), values=(self.dose_entry.get()+" mg", self.modified_entry.get()))
# Increment counter
self.i = self.i + 1
This insert data snippet gives proper output and even shows data in the GUI. But data inserted in gui shows up after execution of for loop. TO be more elaborate .:
print(i) in the above for loop print 0 to 9 in IDLE but during that execution the data shown in the IDLE does not appear simultaneously in GUI. It prints data in IDLE until the loop is not finished and the GUI would not show any data until the loop is finished and then it shows all the numbers all at once.
I want to show data in GUI as it prints in IDLE i.e. for every iteration data should be visible in GUI the as it prints in IDLE. Example:
In first iteration for i = 0
print(i) will print '0'.I want to show it in GUI as it prints in IDLE. Following is my code:
import tkinter
from tkinter import ttk
import urllib
import requests
import time
class Begueradj(tkinter.Frame):
'''
classdocs
'''
def __init__(self, parent):
'''
Constructor
'''
tkinter.Frame.__init__(self, parent)
self.parent=parent
self.initialize_user_interface()
def initialize_user_interface(self):
"""Draw a user interface allowing the user to type
items and insert them into the treeview
"""
self.parent.title("Canvas Test")
self.parent.grid_rowconfigure(0,weight=1)
self.parent.grid_columnconfigure(0,weight=1)
self.parent.config(background="lavender")
# Define the different GUI widgets
self.dose_label = tkinter.Label(self.parent, text = "Dose:")
self.dose_entry = tkinter.Entry(self.parent)
self.dose_label.grid(row = 0, column = 0, sticky = tkinter.W)
self.dose_entry.grid(row = 0, column = 1)
self.modified_label = tkinter.Label(self.parent, text = "Date Modified:")
self.modified_entry = tkinter.Entry(self.parent)
self.modified_label.grid(row = 1, column = 0, sticky = tkinter.W)
self.modified_entry.grid(row = 1, column = 1)
self.submit_button = tkinter.Button(self.parent, text = "Insert", command = self.insert_data)
self.submit_button.grid(row = 2, column = 1, sticky = tkinter.W)
self.exit_button = tkinter.Button(self.parent, text = "Exit", command = self.parent.quit)
self.exit_button.grid(row = 0, column = 3)
# Set the treeview
self.tree = ttk.Treeview( self.parent, columns=('Dose', 'Modification date'))
self.tree.heading('#0', text='Item')
self.tree.heading('#1', text='Dose')
self.tree.heading('#2', text='Modification Date')
self.tree.column('#1', stretch=tkinter.YES)
self.tree.column('#2', stretch=tkinter.YES)
self.tree.column('#0', stretch=tkinter.YES)
self.tree.grid(row=4, columnspan=4, sticky='nsew')
self.treeview = self.tree
# Initialize the counter
self.i = 0
def insert_data(self):
"""
Insertion method.
"""
for l in range(10):
time.sleep(3)
print(l)
self.treeview.insert('', 'end', text="Item_"+str(l), values=(self.dose_entry.get()+" mg", self.modified_entry.get()))
# Increment counter
self.i = self.i + 1
def main():
root=tkinter.Tk()
d=Begueradj(root)
root.mainloop()
if __name__=="__main__":
main()

When you use time.sleep(3) the execution suspends, and also any updates to the GUI. The GUI update tasks are in a queue and they will be handled as soon as the application has time on its hands. And there is no time to spare until the loop ends.
To force the treeview to update you can insert the line:
self.treeview.update_idletasks() # Force widget update
after you have added the treeview item.

Related

Ttk Indeterminate progress bar on button press

I am trying to create a progress bar that runs as long as my function is running to show the user that things are happening and not just frozen. My function (generate_reports) makes queries to the database and writes to CSV files. Here is an abstract version of my code:
from tkinter import *
from tkinter import ttk
from billing import generate_reports
class app:
def __init__(self, root):
self.mainframe = ttk.Frame(root, padding = '4 4 12 12')
self.mainframe.grid(column = 0, row = 0, sticky = (N, W, E, S))
ttk.Button(self.mainframe, text = "Generate Billing Reports", command = self.do_reports).grid(column = 2, row = 3, sticky = (W, E))
def do_reports(self, *args):
pbar = ttk.Progressbar(self.mainframe, orient = HORIZONTAL, mode = 'indeterminate')
pbar.grid(row = 4, column = 3, sticky = (W, E))
t1 = threading.Thread(target = generate_reports, args = [start, end])
t1.start()
pbar.start()
t1.join()
pbar.stop()
return
root = Tk()
BillingApp(root)
root.mainloop()
With this code, the progress bar doesn't pop up until after the generate_reports thread is completed and it is unmoving. If I remove the join, everything works fine but it never stops loading. How can I make the loading bar run for only the duration of the generate_reports thread?
Heh welcome to the fun world of event driven programming :). You can't use join here, the point of that function is to block until the thread is done and the whole point of using a thread is to avoid blocking the mainloop. You have 2 choices: either set up the GUI to constantly poll the thread to see if it's still running, or set up the thread to send a message back to the GUI when it's done. This latter option is probably the cleanest, and it's often done using tkinter's event mechanism.
from tkinter import *
from tkinter import ttk
import threading
import time
def generate_reports(start, end):
print("provide a mcve next time!")
time.sleep(5)
def run_report(root, *args):
generate_reports(*args)
root.event_generate("<<PhishDoneEvent>>") # yes, this is using tkinter in a thread, but some tkinter methods are ok to use in threads
class BillingApp:
def __init__(self, root):
self.mainframe = ttk.Frame(root, padding = '4 4 12 12')
self.mainframe.grid(column = 0, row = 0, sticky = (N, W, E, S))
ttk.Button(self.mainframe, text = "Generate Billing Reports", command = self.do_reports).grid(column = 2, row = 3, sticky = (W, E))
root.bind("<<PhishDoneEvent>>", self.report_done)
def do_reports(self, *args):
# note this makes a new widget with every click ... this is bad. Refactor to reuse the widget.
self.pbar = ttk.Progressbar(self.mainframe, orient = HORIZONTAL, mode = 'indeterminate')
self.pbar.grid(row = 4, column = 3, sticky = (W, E))
start, end = 4,5
t1 = threading.Thread(target = run_report, args = [root, start, end])
t1.start()
self.pbar.start()
def report_done(self, event=None):
self.pbar.stop()
Label(self.mainframe, text="report done").grid(row = 4, column = 3)
root = Tk()
BillingApp(root)
root.mainloop()
I see that you have accepted the answer above. However, I would post my answer since it is not based on threading, which I think is simpler and may be more suitable:
from tkinter import *
from tkinter.ttk import *
import os
root = Tk()
# I set the length and maximum as shown to demonstrate the process in the
# proceeding function
progress = Progressbar(root, orient = HORIZONTAL,
length = 200/5, maximum=200/5, mode = 'determinate')
# Function
def my_func():
t=0
r= 1/5
for i in range(200):
print(i)
t=t+r
progress['value'] = t
root.update_idletasks()
progress.pack()
# Button
Button(root, text = 'Start', command = bar).pack(pady = 10)
mainloop()

Getting variables from a tkinter subwindow

I am currently writing a script in python that takes in user data at the beginning of the script which may need to be updated later.
The initial user data is input through a tkinter window which is then passed along to the lower functions. Later in the script, if the information is detected to be bad, I want to alert the user that the info was bad and prompt them to re-input the data without having to start the program from the beginning.
I was attempting to achieve this by adding in a sub window function that would be called whenever the data needed to be re-input, take the new user input, and then pass it up back up to the function that called it. The code below roughly shows what I'm trying to do:
import tkinter as tk
from tkinter import *
def gui():
window = tk.Tk()
window.geometry('300x200')
L1 = tk.Label(window, text = 'This is a test')
L1.grid(column = 1, row = 0)
L2 = tk.Label(window, text = 'Token')
L2.grid(column = 0, row = 1)
E1 = tk.Entry(window, width = 25)
E1.grid(column = 1, row = 1)
B1 = tk.ttk.Button(window, text = 'Run', command = lambda: shell(window, E1.get()))
B1.grid(column = 1, row = 2)
window.mainloop()
def shell(window, val):
print('Old Val:', val)
val = subwindow_test(window)
print('New Val:', val)
def subwindow_test(window):
def subwinfunc(window, val):
if val == None or val == '':
print('Enter something')
else:
window.sub_win.destroy()
return
window.sub_win = tk.Toplevel(window)
window.sub_win.geometry('300x200')
L1 = tk.Label(window.sub_win, text = 'this is a subwindow')
L1.grid(column = 1, row = 0)
L2 = tk.Label(window.sub_win, text = 'New Token')
L2.grid(column = 0, row = 1, sticky = 'E')
var = StringVar()
E1 = tk.Entry(window.sub_win, width = 25, textvariable = var)
E1.grid(column = 1, row = 1)
B1 = tk.ttk.Button(window.sub_win, text = 'Return', command = lambda: subwinfunc(window, var.get()))
B1.grid(column = 1, row = 2)
window.sub_win.mainloop()
return var.get()
gui()
The idea is to pass the window down to the subwindow_test function, spawn a sub window using tk.Toplevel, ask the user for new data, then destroy the sub window and pass the newly entered data back up to the calling function.
In theory, this would prevent me from having to restart the code from the beginning as this subwindow_test function could be run from anywhere in the code.
The issue is that after subwinfunc returns after destroying window.sub_win, the code hangs until the original window object (the one created in the gui function) is closed. Also, removing the return line from subwinfunc does not change this.
Is there a way to get around this issue?
I have tried using a separate window (An entirely different window, not a sub window of the one created in gui), but the same problem comes up.
It is also not possible, as far as I can tell, to pass the sub window object back up to the calling function and close it there, as subwindow_test cannot return until it breaks from window.sub_win.mainloop() (If the return comes before the mainloop(), the window will never appear) .
Additionally, the only way that I could find to get the value to return at all is to use a StringVar. I would rather try and avoid using global variables, and if I had to guess, I would say that the return val.get() is most likely the root of the problem. However because I can't find another way to pass variables up from this function, I'm stumped.
You should not be calling mainloop more than once. Tkinter provides the ability to wait for a window to be closed before continuing with the wait_window method.
Here is a very simple example that shows how to create a popup dialog that won't return until the user clicks the ok or cancel button.
def get_input():
value = None
def do_ok(event=None):
nonlocal value
value = entry.get()
top.destroy()
def do_cancel():
nonlocal value
value = None
top.destroy()
top = tk.Toplevel()
entry = tk.Entry(top)
ok = tk.Button(top, text="ok", command=do_ok)
cancel = tk.Button(top, text="cancel", command=do_cancel)
entry.bind("<Return>", do_ok)
entry.pack(side="top", fill="x")
ok.pack(side="right")
cancel.pack(side="left")
top.wait_window(top)
return value

Tkinter - dragging mouse across disabled Textbox stops update()

I'm making a program that uses a some kind of widget that from the user's side, lists 'uneditable' and 'unselectable' lines of data.
The widget should also have a scrollbar so my widget options are a bit more limited from what I understand.
Furthermore, the application displays continuously updating numbers.
I went for a textbox - however, when I hold down left click and move my mouse across the textbox root.update() stops/waits.
I wrote some example code below to demonstrate this phenomenon.
import time
from tkinter import *
class App:
def __init__(self):
self.root = Tk()
self.root.geometry("500x500")
self.root.resizable(False, False)
self.main_frame = Frame(self.root)
self.main_frame.grid(row = 0, column = 0, sticky = "news")
self.main_text_box = Text(self.main_frame)
self.main_text_box.grid(row = 0, column = 0, sticky = "news")
self.main_text_box.tag_configure("bold", font = "Helvetica 50")
self.main_text_box.insert(END, "Example text", "bold")
self.main_text_box.configure(state = DISABLED)
def update(self):
self.root.update()
def main():
application = App()
time_start = time.time()
while True:
application.update()
print("Program running, {} seconds since start".format(
round(time.time() - time_start, 3)))
if __name__ == "__main__":
main()
When the user drags the mouse across the textbox, the print statement in
while True:
waits for root.update().
Basically, my question is: Is there any way to not have root.update() wait if the mouse is dragged across a disabled textbox?
(note - I'm new to this site so if I'm being unclear or something, please do point out what I could've done better in my question :))
Thanks!
edit: Sorry, I forgot to mention that I'm using update() because in my actual program (which I didn't post b/c it's 800+ lines), I have other non-tkinter update() methods in the while loop so that I can update other data each frame.
You do not need to manage the loop of the tkinter instance with update() the mainloop() will do this for you.
Instead lets write this where the class inherits from Tk() and then make the time print function part of the class. We can also use after() to update the print. Lastly we should set time_start to a class attribute to be used in our time function.
import time
import tkinter as tk
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.geometry("500x500")
self.resizable(False, False)
self.time_start = time.time()
self.main_frame = tk.Frame(self)
self.main_frame.grid(row = 0, column = 0, sticky = "news")
self.main_text_box = tk.Text(self.main_frame)
self.main_text_box.grid(row = 0, column = 0, sticky = "news")
self.main_text_box.tag_configure("bold", font = "Helvetica 50")
self.main_text_box.insert("end", "Example text", "bold")
self.main_text_box.configure(state = "disabled")
self.time_check()
def time_check(self):
print("Program running, {} seconds since start".format(round(time.time() - self.time_start, 3)))
self.after(100, self.time_check)
if __name__ == "__main__":
my_app = App()
my_app.mainloop()
I could not quite reproduce the problem described; however, some anti-patterns need correction in the code posted:
Use mainloop instead of a while loop.
avoid calling update, the mainloop handles that for you.
Use root.after to repeatedly call a method.
I change your App class to have it inherit from tk.Tk; you could inherit from Frame instead; in this case, you have to provide a master to it.
I also placed the console printing in a function outside the class, as it felt more suitable to keep a console output separated.
import time
import tkinter as tk
class App(tk.Tk):
def __init__(self):
super().__init__()
self.geometry("500x500")
self.resizable(False, False)
self.main_frame = Frame(self)
self.main_frame.grid(row = 0, column = 0, sticky = "news")
self.main_text_box = Text(self.main_frame)
self.main_text_box.grid(row = 0, column = 0, sticky = "news")
self.main_text_box.tag_configure("bold", font = "Helvetica 50")
self.main_text_box.insert(END, "Example text", "bold")
self.main_text_box.configure(state = DISABLED)
self._update_me()
def _update_me(self):
print_time()
self.after(500, self._update_me)
def print_time():
print("Program running, {} seconds since start".format(
round(time.time() - time_start, 3)))
def main():
application = App()
application.mainloop()
if __name__ == "__main__":
time_start = time.time()
main()

Python Tkinter Listbox file implementation

I am currently trying to insert data from an external file which I have defined with the function "browse" as shown below, and these data to implement inside the Listboxes which I have divided in 3 parts, the data in the external file is simply some dates and numbers which I will show below.
Could anyone help me figure out how do I implement data inside a Listbox as shown in the pictures below. P.S datesel() function is date selection to pick up dates manually after implementing the file inside of the listbox in which I am struggling to solve. Lastly Date Listboxes must be only integer as show in the picture 2.Data file link
Current results in 1st picture
Results that I need 2nd picture
Data file picture #3 that I implement through Button 1
from Tkinter import *
import tkFont , time
import ttk,csv,sys,os
import Tkinter,tkFileDialog
class Application(Frame):
def __init__(self,root):
Frame.__init__(self,root)
self.root=root
self.function1()
self.function2()
def function1(self): #tell the machine we are having new widget
self.frame1 = Frame(self.root)
self.frame3 = Frame(self.root, bg="lightblue", borderwidth=2, relief=GROOVE)
self.label1 = Label(self.frame1, text="Upload Acitivity File:")
self.first_button = Button(self.frame1, text="Button 1",command=self.browse)
#Start date selector
self.Sdate = Label(self.frame3, text="Start Date(dd/mm/yy): ")
self.Slb = Listbox(self.frame3, width = 6,height = 8,selectmode='multiple',exportselection=0)
self.Slb2 = Listbox(self.frame3, width=6, height=8,selectmode='multiple',exportselection=0)
self.Slb3 = Listbox(self.frame3, width=6, height=8,selectmode='multiple',exportselection=0)
def function2(self): # # tell the machine where our widget will be
self.frame1.pack()
self.frame3.pack()
self.label1.pack(padx=5, pady=10, side=LEFT)
self.first_button.pack(side=LEFT)
#start and end date
self.Sdate.grid(row =0,column=0)
self.Slb.grid(row =0,column=1)
self.Slb2.grid(row=0, column=2)
self.Slb3.grid(row=0, column=3)
def browse(self):
file = tkFileDialog.askopenfile(mode='rb', title='Choose a file')
self.data = csv.reader(file)
self.datalist = []
for row in self.data:
if len(row) != 0:
self.datalist = self.datalist + [row]
self.datalist.sort()
print self.datalist
def datesel(self):
# get selected line index
self.index = self.Slb.curselection()[0]
# get the line's text
self.seltext = self.Slb.get(self.index)
print self.seltext
self.index2 = self.Slb2.curselection()[0]
self.seltext2 = self.Slb2.get(self.index2)
print self.seltext2
self.index3 = self.Slb3.curselection()[0]
self.seltext3 = self.Slb3.get(self.index3)
print self.seltext3
self.Slist = [self.seltext,self.seltext2,self.seltext3]
self.Slist.sort(0,END)
print self.Slist
def main():
parent=Tk() # main frame
parent.geometry('600x600+300+30') #The height and width of the program
parent.title('Motion Tracker')#assign the title of the program
app = Application(parent)
parent.mainloop()#keeps the program running for infinite amount of time
main()
I don't understand why you want the day, month, and year in separate Listboxes, but anyway, here's some code that shows how to fill 3 Listboxes in the way your 2nd picture shows. I've reduced the code to the bare minimum, and I've hard-coded the filename into the class, but that's easy to fix.
import Tkinter as tk
class Application(tk.Frame):
def __init__(self, root):
tk.Frame.__init__(self, root)
self.pack()
self.root = root
self.do_listboxes()
def do_listboxes(self):
tk.Button(self, text="Get dates", command=self.fill_dates).pack()
self.Slb1 = tk.Listbox(self, width=6, height=8, selectmode='multiple', exportselection=0)
self.Slb2 = tk.Listbox(self, width=6, height=8, selectmode='multiple', exportselection=0)
self.Slb3 = tk.Listbox(self, width=6, height=8, selectmode='multiple', exportselection=0)
self.Slb1.pack(side=tk.LEFT)
self.Slb2.pack(side=tk.LEFT)
self.Slb3.pack(side=tk.LEFT)
def fill_dates(self):
fname = 'dkebz.txt'
# Use sets to get rid of duplicated days, months, and years
days, mons, yrs = set(), set(), set()
with open(fname, 'r') as f:
#Skip header
next(f)
for row in f:
# Extract the date from the row
date = row.split(',')[1]
# Extract the day, month, and year from the date
day, mon, yr = date.split('/')
days.add(day)
mons.add(mon)
yrs.add(yr)
# Populate the list boxes
for day in sorted(days):
self.Slb1.insert(tk.END, day)
for mon in sorted(mons):
self.Slb2.insert(tk.END, mon)
for yr in sorted(yrs):
self.Slb3.insert(tk.END, yr)
def main():
parent = tk.Tk()
parent.title('Motion Tracker')
app = Application(parent)
parent.mainloop()
main()
I've used import Tkinter as tk rather than from Tkinter import *. The "star" import dumps 175 Tkinter names into your namespace (in Python 3, 136 names), which is messy and can cause name collisions, especially if you do other "star" imports. Using import Tkinter as tk means that you have to prefix each Tkinter name with tk., so it involves a little more typing, but it makes the code easier to read because it's clear where each name comes from.
For that, you just need to modify the browse method. I have hard-coded the data to reflect what your file image showed. So if the data is exactly what you provided, this works. If it works for you, uncomment the 2 lines I commented, and delete the self.data list definition I wrote.
def browse(self):
file = tkFileDialog.askopenfile(title='Choose a file')
try:
with open(file, 'r') as reader:
self.data = list(reader)
except:
raise
self.datalist = []
for row in self.data:
if len(row) != 0 and not row.startswith('Activity'):
self.datalist = self.datalist + [row]
activity, date, steps = row.split(',')
month, day, year = date.split('/')
self.Slb.insert(END, month)
self.Slb2.insert(END, day)
self.Slb3.insert(END, year)

python tkinter append list

I am an amateur python programer with 2 months of experience. I am trying to write a GUI to-do list through tkinter. The actual placement of the buttons are not important. I can play around with those after. I need some help with displaying the appended item to the list. In the program, it updates well on the digit, but it won't print onto the list. I double checked it on the console and it says "tkinter.StringVar object at 0x102fa4048" but didn't update the actual list. What I need help is how can I update the list Main_Q on my the label column? Much appreciate some direction and coding help. Thanks.
Main_Q =["read","clean dishes", "wash car"]
from tkinter import*
root=Tk(className="total tasks in the Q")
#formula
def update():
global Main_Q
a=len(Main_Q)
num.set(a)
def add2list():
Main_Q.append(name)
a=len(Main_Q)
num.set(a)
print (Main_Q)
#output
num=StringVar()
y=Label(root, textvariable=num).grid(row=0, column=1)
#input
name=StringVar()
b=Entry(root, textvariable=name).grid(row=7,column=0)
#buttons
z=Button(root, text="update", command=update).grid(row=7, column=2)
add2list=Button(root,text="add", command=add2list).grid(row=7,
column=1)
r = 0
for c in Main_Q:
Label(text=c, relief=RIDGE,width=15).grid(row=r,column=0)
r = r + 1
root.mainloop()
Your problem is that your for loop which build up your labels doesnt get called after each time you have entered a new "task". To easily fix this you can move this loop into your update function.
If you want to prevent of looping through widget everytime you can create a new list with all widgets which already have been created:
createdWidgets = []
widgetsQueue = []
In your update function you than have to iterate through the widgetsQueue (widgetsQueue.pop() for instance), create the widgets and append the widget to the createdWidgetes list.
def update():
global Main_Q
r = 0
for c in Main_Q:
Label(text=c, relief=RIDGE,width=15).grid(row=r,column=0)
r += 1 # shorthand for r = r + 1
Some addition notes:
for the entry it is easier to seperate the definition and placement:
b = Entry(root)
b.grid(row=7,column=0)
because than Entry() returns its instance and you can use it to get the text:
b.get()
if you go shopping do you throw everything into one bag ?
from tkinter import *
does axactly that(in this case the globals() variable would be the bag).If you want to read more about that Importing Python Modules. To prevent that and shorten the amount of letters to type:
import tkinter as t # or tk
root = t.Tk()
*But for sure, if you just want a small program its okay.
Design:
To resolve your problem, you need to design this simple solution:
retrieve the text of the Tkinter.Entry widget using get() method.
add the text you got in 1 to Main_Q using append() method.
bind the button that updates on click both Main_Q and your GUI using command method.
create a new Tkinter.Label widget, set its text to the value you got in 1 and increment its corresponding row in the GUI.
I prefer to organize your code within a class that contains a constructor where Main_Q is initialized so that we call initialize_user_interface() to initialize the GUI with its three elements:
def __init__(self, parent):
Tkinter.Frame.__init__(self, parent)
self.parent = parent
self.Main_Q = ["read", "clean dishes", "wash car"]
self.r = 0 # position of the row of each label
self.initialize_user_interface()
The method initialize_user_interface() does what its name says. We mainly bind the function update_gui() that inserts a new label with the text set to what the user types in Tkinter.Entry widget using command = self.update_gui
ef initialize_user_interface(self):
self.parent.title("Update GUI")
self.parent.grid_rowconfigure(0, weight = 1)
self.parent.grid_columnconfigure(0, weight = 1)
for e in self.Main_Q:
Tkinter.Label(self.parent, anchor = Tkinter.W, text = e).grid(row = self.r, sticky = Tkinter.W)
self.r+=1
self.entry_text = Tkinter.Entry(self.parent)
self.entry_text.grid(row = 0, column = 1)
self.button_update = Tkinter.Button(self.parent, text = "Update", command = self.update_gui).grid(row = 1, column = 1, sticky = Tkinter.E)
Finally, nothing is simpler than update_gui() function:
def update_gui(self):
self.r+=1 # increment the row reserved to the new label
self.Main_Q.append(self.entry_text.get())
Tkinter.Label(self.parent, anchor = Tkinter.W, text = self.entry_text.get()).grid(row = self.r, sticky = Tkinter.W)
Programming the application:
Here is the full program:
'''
Created on Mar 11, 2016
#author: Bill BEGUERADJ
'''
import Tkinter
class Begueradj(Tkinter.Frame):
def __init__(self, parent):
Tkinter.Frame.__init__(self, parent)
self.parent = parent
self.main_queue = ["read", "clean dishes", "wash car"]
self.r = 0
self.initialize_user_interface()
def initialize_user_interface(self):
self.parent.title("Update GUI")
self.parent.grid_rowconfigure(0, weight = 1)
self.parent.grid_columnconfigure(0, weight = 1)
for e in self.main_queue:
Tkinter.Label(self.parent, anchor = Tkinter.W, text = e).grid(row = self.r, sticky = Tkinter.W)
self.r+=1
self.entry_text = Tkinter.Entry(self.parent)
self.entry_text.grid(row = 0, column = 1)
self.button_update = Tkinter.Button(self.parent, text = "Update", command = self.update_gui).grid(row = 1, column = 1, sticky = Tkinter.E)
def update_gui(self):
self.r+=1
self.main_queue.append(self.entry_text.get())
Tkinter.Label(self.parent, anchor = Tkinter.W, text = self.entry_text.get()).grid(row = self.r, sticky = Tkinter.W)
def main():
root = Tkinter.Tk()
b = Begueradj(root)
root.mainloop()
if __name__ == "__main__":
main()
Demo:
Here is a screenshot of the running program:
Note:
I coded the previous program using Python 2.7, so if you want to test it, please change Tkinter to tkinter. Everything else remains the same.

Categories