I am new with python and trying to create two entry widgets to evaluate the data as soon as the user typed in the entry box. How to pass the string var into a function callback so that it will return exactly which entry box has changed. Now the callback function just returns the first entry box (entry1).
Here is my code:
import tkinter
from tkinter import StringVar
main_wd = tkinter.Tk()
my_var1 = StringVar()
my_var2 = StringVar()
def my_callback(var):
print("Traced variables {}".format(var.get())
my_var1.trace('write', my_callback(my_var1))
my_var2.trace('write', my_callback(my_var2))
entry1 = tkinter.Entry(main_wd, textvariable = my_var1).pack(padx = 5, pady = 5)
entry2 = tkinter.Entry(main_wd, textvariable = my_var2).pack(padx = 5, pady = 5)
main_wd.mainloop()
To being in with, the usage of trace is wrong, meaning, the positional argument passed is wrong, it has to be 'w' instead of 'write'. Then next your calling the function when you use (), so you need to use lambda for that. So you trace would be like:
my_var1.trace('w', lambda *_,var=my_var1: my_callback(*_,var=var)) #*_ are the other arguments, like varname,value,mode ?
my_var2.trace('w', lambda *_,var=my_var2: my_callback(*_,var=var))
Then your function would be like:
def my_callback(*args,var):
print("Traced variables {}".format(var.get()))
TIP:
Its better for entry1 and entry2 to not be None, so say:
entry1 = tkinter.Entry(main_wd, textvariable = my_var1)
entry1.pack(padx = 5, pady = 5)
entry2 = tkinter.Entry(main_wd, textvariable = my_var2)
entry2.pack(padx = 5, pady = 5)
When saying pack() on same line as the declaration, it will return what the last method returns. In this case, pack() returns None. So to make those entry widgets reusable, pack() them on separate line. Same applies to grid() and place().
Final Code:
import tkinter
from tkinter import StringVar
main_wd = tkinter.Tk()
my_var1 = StringVar()
my_var2 = StringVar()
def my_callback(*args,var):
print("Traced variables {}".format(var.get()))
my_var1.trace('w', lambda *_,var=my_var1: my_callback(*_,var=var))
my_var2.trace('w', lambda *_,var=my_var2: my_callback(*_,var=var))
entry1 = tkinter.Entry(main_wd, textvariable = my_var1)
entry1.pack(padx = 5, pady = 5)
entry2 = tkinter.Entry(main_wd, textvariable = my_var2)
entry2.pack(padx = 5, pady = 5)
main_wd.mainloop()
Related
I am trying to make a little thing in python like JOpenframe is java and I'm trying to make an entry box. That works fine but when I try to get the value and assign it to variable "t" nothing works. This is what I have:
def ButtonBox(text):
root = Tk()
root.geometry("300x150")
t = Label(root, text = text, font = ("Times New Roman", 14))
t.pack()
e = Entry(root, borderwidth = 5, width = 50)
e.pack()
def Stop():
root.destroy()
g = e.get()
ok = Button(root, text = "OK", command = Stop)
ok.pack()
root.mainloop()
t = ButtonBox("f")
I've tried to make "g" a global variable but that doesn't work. I have no idea how to get the value from this, and I'm hoping someone who does can help me out. Thanks!
If you want to return the value of the entry box after ButtonBox() exits, you need to:
initialize g inside ButtonBox()
declare g as nonlocal variable inside inner function Stop()
call g = e.get() before destroying the window
Below is the modified code:
from tkinter import *
def ButtonBox(text):
g = "" # initialize g
root = Tk()
root.geometry("300x150")
t = Label(root, text = text, font = ("Times New Roman", 14))
t.pack()
e = Entry(root, borderwidth = 5, width = 50)
e.pack()
def Stop():
# declare g as nonlocal variable
nonlocal g
# get the value of the entry box before destroying window
g = e.get()
root.destroy()
ok = Button(root, text = "OK", command = Stop)
ok.pack()
root.mainloop()
# return the value of the entry box
return g
t = ButtonBox("f")
print(t)
trying to learn tkinter and classes with python. I am making a simple word problem generator but cannot understand why I am receiving the same error. I have tried finding resources online to help understand the problem, but most do not involve classes or are woefully brief. I have tried quite a few options to fix, including checking indentation, spelling, changing variable types, etc, but nothing seems to help.Usually this means I am not understanding something fundamental.
When I click on my 'create document' button, which should be bound to the function that passes .get(), I get the following error code:
Error code returned is:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\riley\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 1921, in __call__
return self.func(*args)
File "C:\Users\riley\Documents\Pyth\Test.py", line 174, in get_inputs
minadd = self.e_add_minvar.get()
AttributeError: 'BigWindow' object has no attribute 'e_add_minvar'
Code here:
rad_font = ('Cambria', 20)
class BigWindow:
def __init__(self, root, title, geometry):
self.root = root
self.root.title(title)
self.root.geometry(geometry)
#labels for columns
operator_label = Label(self.root, text = 'Choose options', font = ('cambria', 20, 'bold'))
operator_label.grid(row = 0, column = 0)
#create check buttons
addbutt = IntVar()
subbutt = IntVar()
multbutt = IntVar()
divbutt = IntVar()
Check1 = Checkbutton(self.root, text = 'Addition', variable = addbutt, onvalue = 1, offvalue =0, font = rad_font, pady = 40)
Check1.grid(row = 1, column = 0, sticky = 'W')
Check2 = Checkbutton(self.root, text = 'Subtraction', variable = subbutt, onvalue = 1, offvalue =0, font = rad_font, pady = 40)
Check2.grid(row = 2, column = 0, sticky = 'W')
Check3 = Checkbutton(self.root, text='Multiplication', variable=multbutt, onvalue = 1, offvalue =0, font = rad_font, pady = 40)
Check3.grid(row=3, column=0, sticky = 'W')
Check4 = Checkbutton(self.root, text='Division', variable=divbutt, onvalue=1, offvalue = 0, font = rad_font, pady = 40)
Check4.grid(row=4, column=0, sticky = 'W')
#entry widgets for min max
e_add_minvar = StringVar()
e_add_minvar.set('32')
e_add_min = Entry(self.root, bd = 4, relief = 'sunken', textvariable = e_add_minvar,
selectborderwidth = 5, font = ('Calibri', 20), width = 8)
e_add_min.grid(column = 1, row = 1, padx = 40)
#create/submit button
create_button = Button(self.root, text = 'Create Document', command = self.get_inputs)
create_button.grid(row = 3, column = 4)
self.root.mainloop()
#function to get all inputs to connect to submit/create button
def get_inputs(self):
minadd = self.e_add_minvar.get()
print(minadd)
class Main:
proot = Tk()
Window1 = BigWindow(root, "Word Problem Generator", "900x500")
Main()
Can anyone spot what I am doing wrong or recommend a good learning resource?
Note the formatting is messsed up on pasting, but it is not an indentation issue as far as I can tell.
Thanks in advance
For the fix for those who may stumble on this post in need - It was a scope issue, I had not defined the function e_add_minvar as self.e_add_minvar. Without the 'self.' it was treated as a local variable not an object.
The is going to work like this:
Launcher with buttons to run different functions on other scripts. However when I try launching the "New Account" a new window pops up as it should but the entry field prints blank.
Launcher:
import Setup as s
import Stock as t
from tkinter import *
import os
root = Tk()
root.title("SWM Launcher")
welcome = Label(root, text = "Welcome to the Stock and Wastage Manager Launcher")
welcome.grid(row = 0, column =1, columnspan =3)
l1 = Label (root, text = "Please choose from the options below")
l1.grid(row = 1, column =1, columnspan =3)
submit = Button(root, text = "Open Account", command = lambda: program())
submit.grid(row = 3, column =1)
submit = Button(root, text = "New Account", command = lambda: s.setep())
submit.grid(row = 3, column =2)
What I'm trying to get to work from the setup script
class App:
def __init__(self, window):
window.title("SWM Account Maker")
window.config(bg = "grey")
window.geometry("800x900")
self.searched = StringVar()
name = Entry(window, width = 50, borderwidth = 5,textvariable=self.searched).grid(row = 2, column =1, columnspan =3)
submit = Button(window, text = "Submit", command = lambda: self.name()).grid(row = 3, column =2)
def name (self):
works = self.searched.get()
print(works)
def setep():
root = Tk()
app = App(root)
root.mainloop()
The output i get from the print statement is blank yet if I run setup separately it works fine.I feel like I have miss understood something and no solution's I have found online work. also its my first project working with classes and Tkinter.
It is because you have used multiple instances of Tk(). Either change Tk() to Toplevel() inside setep() function or change self.searched = StringVar() to self.searched = StringVar(window) inside App.init()
I'm designing an app in tkinter, but there is a button that won't show up. The button is crucial to the program's operation.
import tkinter as tk
global field
root = tk.Tk()
root.resizable(0,0)
root.geometry('368x200')
header = tk.Label(root, text = 'Header Text', pady=20)
header.config(font = ('Tahoma', 24))
header.grid(row = 0, columnspan=2)
enter_here = tk.Label(root, text = 'Question: ')
enter_here.grid(row = 1, column = 0, pady = 50)
field = tk.Entry(root, width = 50)
field.grid(row = 1, column = 1, pady = 50)
answer = tk.Button(root, text = 'Answer', command = answerf, width=10)
answer.grid(row=2, column=2)
root.mainloop()
Title, header text and the letters are all placeholders. I just need to figure out how to use the button. I've looked around and couldn't find any answers; most people had just forgot a geometry manager.
You have to be careful what values you are passing to various parameters of tkinter widgets. In above case, this is the reason why you are not able to see button.
Change
field = tk.Entry(root, width = 50)
field.grid(row = 1, column = 1, pady = 50)
to
field = tk.Entry(root, width = 25)
field.grid(row = 1, column = 1, pady = 30)
And,
answer = tk.Button(root, text = 'Answer', command = answerf, width=10)
answer.grid(row=2, column=2)
to
answer = tk.Button(root, text = 'Answer', command = answerf, width=10)
answer.grid(row=1, column=2)
output:
The problem is simply that you're forcing the window to be a size that is too small for the objects inside it.
A simple fix is to remove this line:
root.geometry('368x200')
If you insist on keeping this line, then you need to adjust the parameters of the other widgets so that they fit in the constrained space. For example, you could reduce the size of the widgets or reduce the padding.
I can't figure this out. I want to sum two entries and then put the sum in a label, without any buttons.
In my first example, I only got one entry and that works perfectly and it updates the label when typing.
In my first example I got two entries and I'm trying to pass both into the label (doesn't work).
In my third example, I'll tried to put the result in a list and them sum it and then trying to pass the result to the label, and that dosent work either.
I don't understand how I can pass one entry to the label, but I can't do it with two entries added together!
What to do??
Example one (one entry):
from tkinter import *
root = Tk()
var = DoubleVar()
var.set(float(0.000))
t1 = Entry(root, textvariable = var)
t1.pack()
l = Label(root, textvariable = var)
l.pack()
root.mainloop()
Example two (two entries):
from tkinter import *
root = Tk()
var1 = DoubleVar()
var1.set(float(0.100))
var2 = DoubleVar()
var2.set(float(0.200))
t1 = Entry(root, textvariable = var1)
t1.pack()
t2 = Entry(root, textvariable = var2)
t2.pack()
result = var1 + var2
l = Label(root, textvariable = result)
l.pack()
root.mainloop()
Example tree (two entries, with list): I get this error,
TypeError: unsupported operand type(s) for +: 'int' and 'DoubleVar'
How does I handle this??
from tkinter import *
root = Tk()
var1 = DoubleVar()
var1.set(float(0.100))
var2 = DoubleVar()
var2.set(float(0.200))
t1 = Entry(root, textvariable = var1)
t1.pack()
t2 = Entry(root, textvariable = var2)
t2.pack()
resultList = [var1, var2]
resultSum = sum(resultList)
l = Label(root, textvariable = resultSum)
l.pack()
root.mainloop()
To get the value from a Tkinter Variable you need to use its .get method. And you can use Tkinter's trace mechanism to watch the variables associated with your Entry widgets. Whenever the Entry values change the Label will automatically update.
import tkinter as tk
root = tk.Tk()
var1 = tk.DoubleVar()
t1 = tk.Entry(root, textvariable=var1)
t1.pack()
var2 = tk.DoubleVar()
t2 = tk.Entry(root, textvariable=var2)
t2.pack()
result = tk.DoubleVar()
l = tk.Label(root, textvariable=result)
l.pack()
# Put trace callbacks on the Entry DoubleVars
def set_label(name, index, mode):
result.set(var1.get() + var2.get())
var1.trace('w', set_label)
var2.trace('w', set_label)
# Setting the vars will trigger the trace
var1.set(0.25)
var2.set(0.5)
root.mainloop()
You need to invoke .get() to get the values of your DoubleVars. I don’t have access to tkinter at the moment (using Pythonista) to test this, but you should be able to do something like:
resultList = [var1.get(), var2.get()]
resultSum = sum(resultList)