TKinter window not showing in program with .after() statement - python

I am trying to do a self-updating script to display a table with some data I am scraping from a few websites. The data is scraped, loaded, formatted and then it should be displayed in a table format in TKinter. However, when I make it self-refreshing with root.after() the window does not appear at all. I know the program is running, because I see output in the terminal, but nothing comes up as a TKwindow. Is there something I am missing from .after()'s behaviour? Would it not run when there are a lot of lines?
I tried just commenting the .after() part and the script would execute completely and then show me the window. I also never entered the Else statement, which is fine, but for some reason the code would not work even with just the If statement.
Below is the code I used
root = Tk()
root.geometry("1080x1080")
def calculations():
Scraping_and_writing_in_files()
final_result = File_format_pandas()
if len(final_result.index) == 0:
label = Label(root, text = "There are no hits")
label.pack()
print("I am in the if statement - no hits found")
else:
print("I am in the else statement") # I was never in the Else statement so you can ignore the code below
#Create a main frame
main_frame = Frame(root)
main_frame.pack(fill=BOTH, expand=1)
#Create a canvas
my_canvas = Canvas(main_frame)
my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
#Add scrollbar
my_scrollbar = ttk.Scrollbar(main_frame, orient=VERTICAL, command=my_canvas.yview)
my_scrollbar.pack(side=RIGHT, fill=Y)
#Configure scrollbar
my_canvas.configure(yscrollcommand=my_scrollbar.set)
my_canvas.bind('<Configure>',lambda e: my_canvas.configure(scrollregion = my_canvas.bbox("all")))
def _on_mouse_wheel(event):
my_canvas.yview_scroll(-1 * int((event.delta / 120)), "units")
my_canvas.bind_all("<MouseWheel>", _on_mouse_wheel)
#Create another frame in the canvas
second_frame = Frame(my_canvas)
#Add that new frame to a window in the canvas
my_canvas.create_window((0,0), window=second_frame, anchor = "nw")
initial_entries1 = Entry(second_frame,font=("Helvetica", 12),bd=0,width=30)
initial_entries1.insert(0, "Match Name")
initial_entries1.config(state = "readonly")
initial_entries1.grid(row=0, column=0)
initial_entries2 = Entry(second_frame,font=("Helvetica", 12),bd=0,width=30)
initial_entries2.insert(0, "Result for T1")
initial_entries2.config(state = "readonly")
initial_entries2.grid(row=0, column=1)
initial_entries3 = Entry(second_frame,font=("Helvetica", 12),bd=0,width=30)
initial_entries3.insert(0, "Result for Draw")
initial_entries3.config(state = "readonly")
initial_entries3.grid(row=0, column=2)
initial_entries3 = Entry(second_frame,font=("Helvetica", 12),bd=0,width=30)
initial_entries3.insert(0, "Result for T2")
initial_entries3.config(state = "readonly")
initial_entries3.grid(row=0, column=3)
for thing in range(len(final_result.index)):
match_name = Entry(second_frame, font=("Helvetica", 10),bd=0,width=30)
match_name.insert(0, final_result['Match name'].iloc[thing])
match_name.config(state = "readonly")
match_name.grid(row=thing+1, column=0)
result_t1 = Entry(second_frame, font=("Helvetica", 10),bd=0,width=15)
result_t1.insert(0, final_result['Difference Team 1 For'].iloc[thing])
if float(final_result['Difference Team 1 For'].iloc[thing]) > 0:
result_t1.config(state = "readonly")
result_t1.grid(row=thing+1, column=1)
result_t2 = Entry(second_frame, font=("helvetica", 10), bd=0, width=15)
result_t2.insert(0, final_result['Difference Team 2 For'].iloc[thing])
if float(final_result['Difference Team 2 For'].iloc[thing])>0:
result_t2.config(state = "readonly")
result_t2.grid(row=thing+1, column=3)
result_draw = Entry(second_frame, font=("helvetica", 10), bd=0, width=15)
result_draw.insert(0, final_result['Difference Draw For'].iloc[thing])
if float(final_result['Difference Draw For'].iloc[thing]) > 0:
result_draw.config(state = "readonly")
result_draw.grid(row=thing+1, column=2)
root.after(2000, main_frame.destroy())
# label1 = Label(second_frame, text="Google Hyperlink", fg="blue", cursor="hand2")
# label1.pack()
# label1.bind("<Button-1>", lambda e: callback("http://www.google.com"))
root.after(1000, calculations())
calculations()
root.mainloop()

In the after method no parentheses are needed, since they call the function immediately and will use whatever it returns as callback after the delay. Thank you Jasonharper and Sujay.
root.after(1000, calculations()) => should be root.after(1000, calculations)

Related

how to make a checkbox and check the state of it(if its correct or no)

hello i want to make 3 checkboxes one saying cpu, one saying gpu and one saying cll
and i want to check if the answer is correct so can u show me how to do that
import time
import tkinter as tk
import pygame
window = tk.Tk()
pygame.mixer.init()
img = tk.PhotoImage(file='C:\\Users\\laithmaree\\PycharmProjects\\create_apps_with_python\\brainicon.ico.png')
window.title("Quiz Game")
# pygame.mixer.music.load('ForestWalk-320bit.wav')
# pygame.mixer.music.play()
# i created an icon
# i made a title
window.geometry("800x600")
window.resizable(width=False, height=False)
window.iconphoto(False, img)
label1 = tk.Label(window, text='Quiz App', font=("Arial Bold", 25))
label1.pack()
txtbox = tk.Entry(window, width=50)
def playbuttonclicked():
label1.destroy()
playbtn.destroy()
quitbtn.destroy()
label2 = tk.Label(window, text='What is the short form of computer science',font=("Arial Bold", 25))
label2.pack()
txtbox.place(x=250, y=200, height=40)
def chkanswer():
useranswer = txtbox.get() # Get contents from Entry
if useranswer == 'cs':
lblcorrect = tk.Label(window, text='correct', )
lblcorrect.pack()
def delete():
lblcorrect.destroy()
label2.destroy()
txtbox.destroy()
submitbtn.destroy()
label3 = tk.Label(window, text='whats is the short form of central proccessing unit', font=('Arial Bold', 25))
label3.pack()
lblcorrect.after(1001, delete)
else:
lblwrong = tk.Label(window, text='Try Again')
lblwrong.pack()
def deletefunction():
lblwrong.destroy()
lblwrong.after(1000, deletefunction)
submitbtn = tk.Button(window, text='Submit', font=('Arial Bold', 30), command=chkanswer, bg='red')
submitbtn.place(x=305, y=400)
submitbtn.bind('<Enter>', lambda e: e.widget.config(bg='grey'))
submitbtn.bind('<Leave>', lambda e: e.widget.config(bg='red'))
playbtn = tk.Button(window, text='Play', font=("Arial Bold", 90), bg='red', command=playbuttonclicked)
playbtn.place(x=10, y=200)
playbtn.bind('<Enter>', lambda e: e.widget.config(bg='grey'))
playbtn.bind('<Leave>', lambda e: e.widget.config(bg='red'))
def quitbuttonclicked():
window.destroy()
quitbtn = tk.Button(window, text='Quit', font=("Arial Bold", 90), bg='red', command=quitbuttonclicked)
quitbtn.place(x=400, y=200)
quitbtn.bind('<Enter>', lambda e: e.widget.config(bg='grey'))
quitbtn.bind('<Leave>', lambda e: e.widget.config(bg='red'))
window.mainloop()
the question is label 3 (whats is the short form of central proccessing unit) and i want to make sure the answer is correct because i am creating a quiz app thx
Here is a minimal example of how to create a Checkbutton and to attach a boolean variable and event to it:
import tkinter as tk
window = tk.Tk()
# callback for checkbutton
def checkbox_callback():
is_checked = checkbox_var.get()
print(f"The checkbox is selected: " + str(is_checked))
# variable to store the current value of the checkbutton
checkbox_var = tk.BooleanVar()
# checkbutton with text, variable and callback
checkbox = tk.Checkbutton(window, text="Click me", variable=checkbox_var, command=checkbox_callback)
checkbox.pack()
window.mainloop()

Python tkinter - problem with scrollbar after adding menu column

I'm working on my application connected with my database.
I had a working wersion of it but it didn't look good so I want to add a left side menu to it.
That's how 'show records' page looked like:
photo 1: https://imgur.com/a/egDQpLG
Code of this part:
def createTable(frame, row):
columns = ('IMIĘ','NAZWISKO','PESEL','EMAIL','NR TELEFONU','NR POLISY','DOSTAWCA','WYGASA\nZA (DNI)','NOTATKA','WYŚLIJ\nSMS','WYŚLIJ\nEMAIL')
column_counter = 0
for column in columns:
column_label = Label(frame, text=column, bg=BG_COLOR, fg=TEXT_COLOR, font="Helvetica 10")
column_label.grid(row=row,column=column_counter,padx=2)
column_counter += 1
def addRecord(frame, row, record):
column = 0
for i in range(13): #12 columns in database
if i in (6,7): #records from data base that I don't use
continue
elif i == 11 and notify==True:
send_sms = Button(frame, text="SMS", bg=BG_COLOR, fg=TEXT_COLOR, font="Helvetica 10", command=partial(sendSMSNotification, [], record[5])) #button that sends sms
send_sms.grid(row=row,column=9,padx=2)
elif i == 12 and notify==True:
send_email = Button(frame, text="EMAIL", bg=BG_COLOR, fg=TEXT_COLOR, font="Helvetica 10", command=partial(sendEmailNotification, [], record[5])) #button that sends EMAIL
send_email.grid(row=row,column=10,padx=2)
else:
result_label = Label(frame, text=record[i], bg=BG_COLOR, fg=TEXT_COLOR, font="Helvetica 10")
result_label.grid(row=row,column=column,padx=2)
column += 1
def showRecords():
destroyWidgets() #clears window
main_frame = Frame(root, bg=BG_COLOR)
main_frame.pack(fill=BOTH, expand=1)
my_canvas = Canvas(main_frame, bg=BG_COLOR)
my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
my_scrollbar = ttk.Scrollbar(main_frame, orient=VERTICAL, command=my_canvas.yview)
my_scrollbar.pack(side=RIGHT, fill=Y)
my_canvas.configure(yscrollcommand=my_scrollbar.set)
my_canvas.bind('<Configure>', lambda e:
my_canvas.configure(scrollregion=my_canvas.bbox("all")))
second_frame = Frame(my_canvas, bg=BG_COLOR)
my_canvas.create_window((0,0), window=second_frame, anchor="nw")
conn = sqlite3.connect(dbname)
c = conn.cursor()
back_button_top = Button(second_frame, text='Powrót', width=135, command=lambda: returnMain())
back_button_top.grid(row=0, column=0, pady=20, padx=20)
result_frame = Frame(second_frame, bg=BG_COLOR)
result_frame.grid(row=1, column=0)
createTable(result_frame, 0) #creates a heading of the table ('IMIĘ, NAZWISKO, PESEL' etc)
c.execute("SELECT * FROM dane")
records = c.fetchall()
row_counter = 2
for record in records:
addRecord(result_frame, row_counter, record) #adds a line of data read from the database, looked like a excel
row_counter+=1
Then I added a simple left sided menu column. So I added these lines to the showrecords function.
showMenu creates a Frame in column 0 and adds some buttons
def showMenu():
menu_frame = Frame(root,bg=BG_COLOR)
menu_frame.grid(row=0,column=0, sticky='ew')
menu_frame.grid_columnconfigure(0, weight=1)
show_records_button = Button(....
def showRecords():
destroyWidgets()
showMenu()
record_frame = Frame(root, bg=BG_COLOR)
record_frame.grid(column=1, row=0,sticky='nsew')
main_frame = Frame(record_frame, bg=BG_COLOR)
main_frame.pack(fill=BOTH, expand=1)
......
photo 2: https://imgur.com/iaRIAd9
And now I'm getting the scrollbar in the center of records column. Do you know how can I move the scroll to the right side of window? I think I have tried to change every possible attribute and nothing helped.
Also the problem of small Frame appears if I add an addition (just like my new version of code but without line with showMenu() Frame without adding a menu. So probably something is wrong with the sizing, but I dont know what.

Tkinter window geometry

I'm working on Tkinter window, and I want to set up the height and width of the screen without the geometry function, so I made 2 scales vertical and horizontal, then I use a button with a command that set up the window size in the following code:
root = Tk()
root.title("Root window")
label = Label(root, text="The height").pack()
slay = Scale(root, from_=0, to=200)
slay.pack()
my_label = Label(root, text="The width").pack()
hor = Scale(root, from_=0, to=250, orient=HORIZONTAL)
hor.pack()
def btns():
root.geometry(str(f"{slay.get} x {hor.get}"))
btn = Button(root, text="Setup the window size", command=btns).pack()
And the error is:
line 20, in btns
root.geometry(str(f"{slay.get} x {hor.get}"))
You are just referencing the .get() function, never actually calling them. So you will receive an error.
Call the function using (). Also, there is no space between str(f"{slay.get()} x {hor.get()}").
So it would look something like this:
root.geometry(str(f"{slay.get()}x{hor.get()}"))
This works.
The problem was root.geometry(str(f"{vert.get} x {hori.get}"))
I changed it to this root.geometry(str(f"{vert.get()}x{hori.get()}"))
Simply removed the spaces around 'x' and added () to the get
Also added orient = VERTICAL to slay
root = Tk()
root.title("Root window")
label = Label(root, text="The height").pack()
slay = Scale(root, from_=0, to=200, orient=VERTICAL)
slay.pack()
my_label = Label(root, text="The width").pack()
hor = Scale(root, from_=0, to=250, orient=HORIZONTAL)
hor.pack()
def btns():
print( slay.get(), hor.get() )
root.geometry(str(f"{slay.get()}x{hor.get()}"))
btn = Button(root, text="Setup the window size", command=btns).pack()
root.mainloop()

How to fix most recent Label gets cut off Python Tkinter when using scrollbar

So I was making a chat gui for my tcp chat and I wanted to use a scrollbar so you would be able to see the messages no matter how long the messages got. So I was testing somethings and got it to work for the most part. The only problem is that the most recent message after filling the viewable frame get cut off. Then every most recent message is cut off no matter if you scroll all the way down.
This is after I typed 1 more msg than what fits in the frame (notice how the scrollbar is still disabled)
Here I stretched the window down so you could see that the label is there it is just that the scrollbar did not update for just that label
from tkinter import *
from tkinter.ttk import Combobox
from tkinter import messagebox
from time import sleep
w = Tk()
w.title('Title')
w.geometry('500x400')
w.resizable(width=False, height=False)
def send():
if send_entry.get() != '':
messages.append(send_entry.get())
i = 0
for msg in messages:
Label(chat_frame, text=f'User: {msg}').grid(column=0, row=i, padx=10, sticky=W)
i += 1
canvas.configure(scrollregion=canvas.bbox("all"))
send_entry.delete(0, 'end')
def sendEvent(event):
if send_entry.get() != '':
messages.append(send_entry.get())
i = 0
for msg in messages:
Label(chat_frame, text=f'User: {msg}').grid(column=0, row=i, padx=10, sticky=W)
i += 1
canvas.configure(scrollregion=canvas.bbox("all"))
send_entry.delete(0, 'end')
messages = []
main_frame = Frame(w)
main_frame.pack(fill=BOTH, expand=1, pady=10)
canvas = Canvas(main_frame)
canvas.pack(side=LEFT, fill=BOTH, expand=1, pady=10)
scrollbar = Scrollbar(main_frame, orient=VERTICAL, command=canvas.yview)
scrollbar.pack(side=RIGHT, fill=Y)
canvas.configure(yscrollcommand=scrollbar.set)
canvas.bind('<Configure>', lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
chat_frame = Frame(canvas)
canvas.create_window((0, 0), window=chat_frame, anchor=NW)
bot_frame = Frame(w).pack(side=BOTTOM)
send_entry = Entry(bot_frame, width=55)
send_entry.pack(side=LEFT, padx=30, pady=10)
send_button = Button(bot_frame, text='Send', command=send).pack(side=LEFT)
w.bind('<Return>', sendEvent)
w.mainloop()
First you should bind <Configure> on chat_frame instead of canvas. Second you need to update the canvas before updating scrollregion option.
Also you can combine send() and sendEvent() as they do the same thing. And don't create new set of labels every time a new message is added, just create a new label for the newly added message.
from tkinter import *
from tkinter.ttk import Combobox
#from tkinter import messagebox
#from time import sleep
w = Tk()
w.title('Title')
w.geometry('500x400')
w.resizable(width=False, height=False)
def send(event=None):
msg = send_entry.get().strip()
if msg != '':
messages.append(msg)
Label(chat_frame, text=f"User: {msg}").grid(padx=10, sticky=W)
send_entry.delete(0, 'end')
# make the last message visible
canvas.update()
canvas.yview_moveto(1)
messages = []
main_frame = Frame(w)
main_frame.pack(fill=BOTH, expand=1, pady=10)
canvas = Canvas(main_frame)
canvas.pack(side=LEFT, fill=BOTH, expand=1, pady=10)
scrollbar = Scrollbar(main_frame, orient=VERTICAL, command=canvas.yview)
scrollbar.pack(side=RIGHT, fill=Y)
canvas.configure(yscrollcommand=scrollbar.set)
#canvas.bind('<Configure>', lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
chat_frame = Frame(canvas)
canvas.create_window((0, 0), window=chat_frame, anchor=NW)
chat_frame.bind('<Configure>', lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
bot_frame = Frame(w)
bot_frame.pack(side=BOTTOM)
send_entry = Entry(bot_frame, width=55)
send_entry.pack(side=LEFT, padx=30, pady=10)
Button(bot_frame, text='Send', command=send).pack(side=LEFT)
w.bind('<Return>', send)
w.mainloop()
However better use ScrolledText widget instead for the chat messages box.

Tkinter - Scrollbar does not resize when number of labels inside a frame changes

I am trying to create a GUI where left hand side is a Listbox (contained inside a frame f2) that displays employee ID's and right side is another frame second_frame (contained inside canvas and outer frame f3) that shows transaction details of each selected employee in the form of labels.
Each employee can have multiple transactions. So, The number of labels had to be dynamic, i.e. for first selected item in listbox, there could be two labels and for second selected item in listbox, it could be hundred. For every selection, I am calling two functions to destroy old labels and create new labels. While the code works fine, I am having trouble resizing the scrollbar according to the selected listbox entry. I am new to Tkinter, Please advise. Below is my code.
Also note, the test() function when called from outside any function displays the scroll bar, but does not display anything when called from within any function.
# -*- coding: utf-8 -*-
from tkinter import *
'''def test():
for i in range(0,50):
for j in range (0,7):
Label(second_frame, text=f'{i}{j}', width=20).grid(row=i, column=j, pady=5,padx=5)
'''
# --- function ---
def destroy_frame():
#f1.grid_forget()
print("destroying frame")
for label in second_frame.winfo_children():
label.destroy()
def create_frame(val):
print("creating new frame")
for i in range(0,val):
for j in range (5):
Label(second_frame, text=f'{i} {j} ', relief=GROOVE, width=10).grid(row=i, column=j, pady=5,padx=5)
def on_selection(event):
# here you can get selected element
print('previous:', listbox.get('active'))
print(' current:', listbox.get(listbox.curselection()))
# or using `event`
print('(event) previous:', event.widget.get('active'))
print('(event) current:', event.widget.get(event.widget.curselection()))
print (listbox.get(listbox.curselection()))
if (listbox.get(listbox.curselection()) == "Eid 1"):
destroy_frame()
create_frame(100)
elif (listbox.get(listbox.curselection()) == "Eid 2"):
destroy_frame()
create_frame(200)
print('---')
root = Tk()
root.geometry('800x500')
#Create base Frames
f1 = Frame(width=800, height=50, bg="yellow", colormap="new")
f1.grid(row=0, columnspan=2)
f1.grid_propagate(False)
f2 = Frame(width=200, height=425, bg="light blue", colormap="new")
f2.grid(row=1, column=0)
f2.grid_propagate(False)
f3 = Frame(width=600, height=425, bg="light green", colormap="new")
f3.grid(row=1, column=1)
f3.grid_propagate(False)
#Create header Label
l1_f1 = Label(f1, text="Employee Purchase Entries:", bg="yellow")
l1_f1.grid(row=0, column=0)
#Create Listbox
listbox = Listbox(f2, bg="light blue", width=40, height=400)
listbox.grid(row=0, column=0)
#Add Scrollbar to ListBox
list_scrollbar = Scrollbar(f2)
list_scrollbar.grid(row=0, column=1, sticky=NSEW)
#Enter Listbox Data
listbox.insert(1, 'Eid 1')
listbox.insert(2, 'Eid 2')
listbox.bind('<<ListboxSelect>>', on_selection)
#configure the Listbox and Scrollbar
listbox.config(yscrollcommand = list_scrollbar.set)
list_scrollbar.config(command = listbox.yview)
#Create a Canvas
my_canvas = Canvas(f3, width=580, height=425, bg="light green")
#my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
my_canvas.grid(row=0, column=0)
#Add a Scrollbar to the canvas
my_scrollbar = Scrollbar(f3, orient=VERTICAL, command=my_canvas.yview)
my_scrollbar.grid(row=0, column=1, sticky=NSEW)
#configure the canvas
my_canvas.configure(yscrollcommand=my_scrollbar.set)
my_canvas.bind('<Configure>', lambda e : my_canvas.configure(scrollregion = my_canvas.bbox("all")))
#Create another frame inside the canvas
second_frame = Frame(my_canvas)
#Add the new frame to a window in the canvas
my_canvas.create_window((0,0), window=second_frame, anchor="nw")
#test()
root.mainloop()
Your canvas isnt trigger the configure event when you add widgets to your frame. Instead your frame is been triggerd.
So you need to put this line:
second_frame.bind('<Configure>', lambda e : my_canvas.configure(scrollregion = my_canvas.bbox("all")))
after creating second_frame

Categories

Resources