How to get Int value from spinbox to create new entries - python-3.x

I created a simple spin box. what I want is, as I increase or
decrease the value in spin box, a new entry should be created or
deleted respectively.
I am not able to get the Int value from the spinbox.
I tried, user_input = int(sb.get()), But this also didn't work.
I am getting this error,
'str' object cannot be interpreted as an integer.
,,,
1st code:
from tkinter import *
root = Tk()
sb_var = IntVar()
sb = Spinbox(root, bg='gray', textvariable=sb_var)
sb.pack()
user_input = sb.get()
for x in range(user_input):
my_entry = Entry(root)
my_entry.pack()
root.mainloop()
,,,
2nd code:
from tkinter import *
root = Tk()
root.geometry("500x400")
def up_or_down(direction):
if direction == "up":
my_entry = Entry(root)
my_entry.pack()
if direction == "down": # I don't know how to code this condition
my_entry.destroy()
tcl_up_or_down = root.register(up_or_down)
sb = Spinbox(root, from_=0, to=100, bg='gray', command=(tcl_up_or_down, '%d'))
sb.pack()
root.mainloop()
'''

Related

call a function if the frame widget gets the focus in python(tkinter)

In working.py , I get the focused frame using focus().
In calculations.py, I am trying to run some calculations which depends on which frame is focused.
I am calling calculations() on btn which is in main.py.
What I am trying to achieve is that when I click Calculate button,
if e1_frame is focused I should get the addition of 2 numbers and
when e2_frame is focused I should get the multiplication of those 2 numbers.
But instead I get the following error:
TypeError: <lambda>() missing 1 required positional argument: 'e'
main.py
from tkinter import *
from working import create_frames
from calculations import calculations
class MyApp:
def __init__(self, root):
self.root = root
self.var_e1 = StringVar(None)
self.var_e2 = StringVar(None)
self.var_lbl = StringVar(None)
self.var_status_lbl = StringVar(None)
create_frames(self)
e1 = Entry(self.e1_frame, textvariable=self.var_e1)
e2 = Entry(self.e2_frame, textvariable=self.var_e2)
e1.focus_set()
e1.pack()
e2.pack()
btn = Button(self.btn_frame, text='Calculate', command=lambda e: calculations(self, e))
btn.pack()
lbl = Label(self.root, font=20, textvariable=self.var_lbl)
self.var_lbl.set('0')
lbl.pack()
status_lbl = Label(self.root, textvariable=self.var_status_lbl)
status_lbl.pack(side=BOTTOM)
self.var_status_lbl.set('Nothing is selected.')
def main():
root = Tk()
root.geometry('400x400')
MyApp(root)
root.mainloop()
if __name__ == '__main__':
main()
working.py
from tkinter import *
def focus(self, event):
if event.widget == self.e1_frame:
self.var_status_lbl.set(f'First value: {self.var_e1.get()}')
if event.widget == self.e2_frame:
self.var_status_lbl.set(f'Second value: {self.var_e2.get()}')
def create_frames(self):
e0_frame = Frame(self.root)
self.e1_frame = Frame(e0_frame)
self.e2_frame = Frame(e0_frame)
e0_frame.pack()
self.e1_frame.pack(side=LEFT)
self.e2_frame.pack(side=LEFT)
self.btn_frame = Frame(self.root)
self.btn_frame.pack(pady=10)
self.e1_frame.bind('<Enter>', lambda e: focus(self, e))
self.e2_frame.bind('<Enter>', lambda e: focus(self, e))
calculations.py
from tkinter import *
def calculations(self, event):
value1 = int(self.var_e1.get())
value2 = int(self.var_e2.get())
if event.widget == self.e1_frame:
result = value1 + value2
if event.widget == self.e2_frame:
result = value1 * value2
result = value1 + value2
self.var_lbl.set(result)
This line seems problematic to me:
lambda e: calculations(self, e)
While you define a lambda for a button command you set the argument e which commonly stands for event, which refers to an EvenObject produced by tkinter and passed as argument to the bounded function/method.
Enough of the context and lets see how we can fix your code. I would suggest to make calculation an ordinary method and leave that event object for cases where it is more needed. You can simply get which entry has the keyboard focus by calling focus_get(), which can easily replace your event.widget if statement.
import tkinter as tk
def cmd():
print(root.focus_get())
root = tk.Tk()
e1 = tk.Entry()
e2 = tk.Entry()
b1 = tk.Button(command=cmd)
e1.pack()
e2.pack()
b1.pack()

How to insert a loop function into a label in Tkinter (self_updatable)

I have this loop that runs and changes x, how should I put it into a Tkinter label? Thanks in advance.
from tkinter import *
import time
root = Tk()
def x_loop():
x = 0
while x <= 100:
time.sleep(2)
x = x + 1
l = Label(root, text = x_loop).pack(pady = 20)
root.mainloop()
Tkinter dosent like while loops, this is because a while loop dosent return to the mainloop till its finished and therefore you application isnt working during this time.
Tkinter provides for this the .after(*ms,*func) method and is used below.
Also for changing the text of a tk.Label you can go for several ways. I think the best way is to use the inherated option textvariable.
The textvariable needs to be a tk.*Variable and configures the tk.Label as soon as the var is set.
Check out the working example below:
import tkinter as tk
x = 0
def change_text():
global x
var.set(x)
x +=1
root.after(100,change_text)#instead of a while loop that block the mainloop
root = tk.Tk()
var = tk.StringVar()
lab = tk.Label(root, textvariable=var)
lab.pack()
change_text()
root.mainloop()
Instead of using StringVar as #Atlas435 did, you can use this simpler method:
import tkinter as tk
def x_loop():
global x
if x <= 100:
x += 1
# Update the label
label.config(text=x)
# after 2000 ms call `x_loop` again
root.after(2000, x_loop)
x = 0
root = tk.Tk()
label = tk.Label(root, text=x)
label.pack(pady=20)
# STart the loop
x_loop()
root.mainloop()

How to make a variable equal to the input received from the input field in tkinter?

I was wondering how to make this code work.I always get 12 in the console.
from tkinter import *
s = 12
root = Tk()
root.geometry("200x200")
root.title("Program")
e = Entry(root)
e.pack()
def clicked():
e.get = s
print(s)
button = Button(root,command=clicked,text="ok")
button.pack()
root.mainloop()
You have to change the function clicked as follows:
def clicked():
s=e.get()
print(s)
There were two errors in your code:
You were trying to assign the value 12 to a function.
You were not calling the function (using parenthesis).
this line here:
e.get = s
says the method of e named get is equally to s.
Which is nonsense. You want s to be equally to what is returned by e.get.
to have something returned you need to invoke this method first.
So the logical right way to do this is by:
s = e.get()
Note that it is a variable in the enclosed namespaces of your function.
To make it global you need to global the variable.
from tkinter import *
s = 12
root = Tk()
root.geometry("200x200")
root.title("Program")
e = Entry(root)
e.pack()
def clicked():
#global s
s = e.get()
print(s)
button = Button(root,command=clicked,text="ok")
button.pack()
b2 = Button(root, text='print', command=lambda:print(s))
b2.pack()
root.mainloop()
I have used .place() instead of .pack() and placed my same entry on the same position as it was place before, but this time if value changes as you click on button OK.
Use e.insert(0,"Value") to insert any value in a entry.
This worked for me. Also let me know did it worked for you as well?
from tkinter import *
s = 12
root = Tk()
root.geometry("200x200")
root.title("Program")
e = Entry(root)
e.place(relx=0.1, rely = 0.1)
def clicked():
e = Entry(root)
e.insert(0, s)
e.place(relx=0.1, rely = 0.1)
button = Button(root,command=clicked,text="ok")
button.place(relx=0.4, rely = 0.2)
root.mainloop()

How to make a label cycle through preset words or phrases when a button is pressed in tkinter

So I'm trying to make it cycle through each letter of the alphabet when the button is clicked.
I have tried the method i am showing now.
I have also tried many others and i couldn't get anything to work.
If you do have a solution please try keep it simple i am kinda new too this.
from tkinter import *
win = Tk()
win.title('ab')
a = 0
def changetext():
a = a+1
if a == 1:
lbl.config(text='b')
def changetext():
if a == 2:
lbl.config(text='c')
lbl = Label(win,text='a')
lbl.grid(row=1,column=1)
btn = Button(win,text='u', command =changetext)
btn.grid(row=2,column=1)
win.mainloop()```
In python, variables inside functions are local, which means that if you define a variable a = 0 outside the function, then do a = 1 in the function, the a equals 1 inside the function but it still equals 0 outside. If you want to change the value of a outside the function from inside the function, you need to declare a as a global variable (see code below).
import tkinter as tk # avoid import * to because it leads to naming conflicts
win = tk.Tk()
win.title('ab')
i = 0
letters = "abcdefghijklmnopqrstuvwxyz"
def changetext():
global i # change value of i outside function as well
i += 1
i %= 26 # cycle through the alphabet
lbl.configure(text=letters[i])
lbl = tk.Label(win, text='a')
lbl.grid(row=1, column=1)
btn = tk.Button(win,text='u', command=changetext)
btn.grid(row=2, column=1)
win.mainloop()
You can use itertools.cycle to create a cycle list and then use next() function to get the next item in the cycle list:
import tkinter as tk
from itertools import cycle
words = cycle(['hello', 'world', 'python', 'is', 'awesome'])
root = tk.Tk()
lbl = tk.Label(root, text=next(words), width=20)
lbl.pack()
tk.Button(root, text='Next', command=lambda: lbl.config(text=next(words))).pack()
root.mainloop()
I actually used the first method and adapted it by making the variable global because then it will update it for all the functions making my first method work
from tkinter import *
win = Tk()
win.title('ab')
i = 0
def changetext():
global i
i = i + 1
if i == 1:
lbl.config(text='word 2')
if i == 2:
lbl.config(text='word 1 ')
lbl = Label(win,text='a')
lbl.grid(row=1,column=1)
btn = Button(win,text='u', command =changetext)
btn.grid(row=2,column=1)
win.mainloop()

Need to get the values from 2 calender funtions, find the difference and store it in label widget

i have tried most things possible here but could get it to work. any help would be highly appreciated.
I want the users to select the dates AND THEN get theose values, storeit in a and b, find the difference, and store it in y.
But what is actually happening is, when i call cal_fun1, it gets the value of b even before allowing the user selection.
how can i change this? Also i need the value to be stored in L3, as the difference.
from tkinter import *
from tkcalendar import Calendar, DateEntry
def pay_cal():
def cal_fun():
t = Toplevel()
global cal
cal = Calendar(t, year=2019, month=6, day=1, foreground='Blue', background='White', selectmode='day')
cal.pack()
cal.bind("<<CalendarSelected>>",lambda e: c.set(cal.get_date()))#make use of the virtual event to dynamically update the text variable c
def cal_fun1():
t = Toplevel()
global cal1, y
cal1 = Calendar(t, foreground='Blue', background='White', selectmode='day')
cal1.pack()
cal1.bind("<<CalendarSelected>>", lambda e: d.set(cal1.get_date()) ) # make use of the virtual event to dynamically update the text variable c
a=cal.selection_get()
b=cal1.selection_get()
y =a-b
print(y) #this is only for testing the output
sub_win = Tk()
sub_win.geometry('400x500+600+100')
sub_win.title('Payout Calculator')
c = StringVar() #create a stringvar here - note that you can only create it after the creation of a TK instance
c.set(0)
d = StringVar() # create a stringvar here - note that you can only create it after the creation of a TK instance
d.set(0)
y = StringVar()
l1 = Button(sub_win, text= 'Check-In Date:', command= cal_fun)
chck_in_date = Label(sub_win, textvariable=c)
l1.grid(row=1)
chck_in_date.grid(row=1, column=2)
l2 = Button(sub_win, text='Can Date:', command=cal_fun1)
q = Label(sub_win, textvariable=d)
l2.grid(row=2)
q.grid(row=2, column=2)
total_days = Label(sub_win, textvariable= y.get())
L3 = Label(sub_win, text="Total Days")
L3.grid(row=3)
total_days.grid(row=3, column=2)
sub_win.mainloop()
pay_cal()

Resources