I'm trying to put old school sequential Tkinter code into class structure code.
So let's consider this example :
import Tkinter as Tk
def StartProcess():
print Text_1_Var.get(), Text_2_Var.get(), Text_3_Var.get()
if __name__ == '__main__':
MainFrame = Tk.Tk()
Tk.Button(MainFrame , text = "Start",command=StartProcess).grid(column=2, row=0)
Tk.Label(MainFrame , text = "1").grid(column=1, row=1)
Text_1_Var = Tk.StringVar()
Text_1 = Tk.Entry(MainFrame , width=40, textvariable = Text_1_Var).grid(column=2, row=1)
Tk.Label(MainFrame , text = "2").grid(column=1, row=2)
Text_2_Var = Tk.StringVar()
Text_2 = Tk.Entry(MainFrame , width=40, textvariable = Text_2_Var).grid(column=2, row=2)
Tk.Label(MainFrame , text = "3").grid(column=1, row=3)
Text_3_Var = Tk.StringVar()
Text_3 = Tk.Entry(MainFrame , width=40, textvariable = Text_3_Var).grid(column=2, row=3)
# etc
MainFrame.mainloop()
On press "Start" it displays values of Entry from 1 to 3.
Now i recode it as follow :
import Tkinter as Tk
def StartProcess():
print "???"
class NewEntry(Tk.Frame):
def __init__(self,master=None,idnumber=None):
Tk.Frame.__init__(self,master)
self.pack(side=Tk.TOP)
self.CreateWidgets(idnumber)
def CreateWidgets(self,idnumber):
Tk.Label(master=self, text = idnumber).grid(column=1, row=0)
self.Text_Var = Tk.StringVar()
self.Text = Tk.Entry(master=self, width=40, textvariable = self.Text_Var).grid(column=2, row=0)
if __name__ == '__main__':
MainFrame = Tk.Tk()
Tk.Button(master=MainFrame,text="Start", command=StartProcess).pack()
for i in range (1, 4): # or more
NewEntry(master=MainFrame,idnumber=str(i))
MainFrame.mainloop()
GUI are both identical. I want to get the same result but i don't know where my function StartProcess should take place and how extract value of each self.Text_Var instance.
It's not enough to create a NewEntry object; you need to save references to them so you can access them later (e.g., from StartProcess).
entries = []
for i in range (1, 4): # or more
e = NewEntry(master=MainFrame,idnumber=str(i))
entries.append(e)
# Or more simply,
# entries = [NewEntry(master=MainFrame, idnumber=str(i)) for i in range(1,4)]
Then, StartProcess becomes something like
def StartProcess():
strings = [x.Text_Var.get() for x in entries]
print " ".join(strings)
Related
im trying to name a button what it is named in ent and so it doesn't repeat when the button is pressed again so if you press once it's button1 and again button2
from tkinter import *
def ext():
win1.destroy()
but1 = Button(root, text=txt.get(), height=10, width=30)
but1.grid(padx=3, row=0, column=1)
def create():
global win1
global txt
win1 = Tk()
win1.geometry("200x200")
ent = Entry(win1)
ent.pack(pady=20)
txt = ent.get()
sub = Button(win1, text="Submit", command=ext)
sub.pack()
root = Tk()
root.geometry("750x750")
root.config(background="#6673ED")
create_but = Button(root, text="Create new card", height=10, width=30, command=create)
create_but.grid(row=0,column=0)
root.mainloop()
The code below uses a dictionary of lists to add an integer to any repeating text input. I think this is what the question is about.
import tkinter as tk # import as tk is safer and more flexible
# Globals to keep it simple
names = {} # Dictionary. Will become a dictionary of lists.
row = 1
col = 0
win1 = None
ent = None
def add_text( txt ):
""" Adds txt to the names dictionary if it doesn't already exist.
Adds and integer to the txt if it does already exit """
name = names.get( txt, None )
if name:
name.append( txt + str(len( name )) ) # Append `txt + int` to a list
else:
names[ txt ] = [ txt ] # Add a list of one item to the dict.
# print( names ) # Uncomment to see what is happening.
return names[ txt ][-1]
def ext():
global row, col
txt = ent.get() # Get the text from the entry
win1.destroy() # before the window is destroyed
txt = add_text( txt )
but1 = tk.Button(root, text=txt, height=10, width=30)
but1.grid(padx=3, row=row, column=col) # row and column need to
# change to show all buttons.
col += 1
if col > 2:
row += 1
col = 0
def create():
global win1
global ent
win1 = tk.Toplevel() # Create a second window with tk.Toplevel.
# Never create two tk.Tk objects.
win1.geometry("200x200")
ent = tk.Entry(win1)
ent.pack(pady=20)
ent.focus() # Position the focus in the Entry
# txt = ent.get() # removed as the Entry was being read before data was entered.
# The entry is now read in `ext`.
sub = tk.Button( win1, text="Submit", command=ext )
sub.pack()
root = tk.Tk()
root.geometry("750x750")
root.config(background="#6673ED")
create_but = tk.Button(root, text="Create new card", height=10, width=30, command=create)
create_but.grid(row=0,column=0)
root.mainloop()
Running python 3.8 in PyCharm
I'm trying to create a class to allow creation of a tkinter checkbutton (and eventually other widgets) that will hold all the formatting and definition for the widget. I would like to be able to test the state of the checkbutton and act on it in a callback. But like many others, my checkbutton variable seems to always be 0. I'm fairly sure its a garbage collection issue, but I can't figure a way around it. Note the second set of parameters in the class definition specify the location of the label to display the checkbutton variable state. At the moment, the callback is just to display the variable state in a label.
Acknowledgement:
I modified code from Burhard Meier's book "Python GUI Programming Cookbook" for this. The code related to the class is mine, the rest is from Burkhard Meier.
'''
This is a modification of code by Burhard A. Meier
in "Python GUI Programming Cookbook"
Created on Apr 30, 2019
#author: Burkhard A. Meier
'''
#======================
# imports
#======================
import tkinter as tk
from tkinter import ttk
# Create instance
win = tk.Tk()
# Add a title
win.title("GUI Test Box")
# Modify adding a Label
a_label = ttk.Label(win, text="Testing TK Widgets")
a_label.grid(column=0, row=0)
# Modified Button Click Function
def click_me():
action.configure(text='Hello ' + name.get() + ' ' +
number_chosen.get())
#Define the Checkbutton Class
class ChkBut(): #lable, xloc, yloc, xlab, ylab
def __init__(self, lable, xloc, yloc, xlab, ylab): # , xloc, yloc, text="default", variable = v, onvalue='Set', offvalue='NotSet'):
v = tk.IntVar()
self.v = v
self.lable = lable
self.xloc = xloc
self.yloc = yloc
self.xlab = xlab
self.ylab = ylab
c = tk.Checkbutton(
win,
text= self.lable,
variable=self.v,
command=self.cb(self.v, xlab,ylab))
c.grid(column=xloc, row=yloc, sticky = tk.W)
c.deselect()
def cb (self, c, xlab, ylab):
if c.get()==1:
c_label = ttk.Label(win, text="Set")
c_label.grid(column=xlab, row=ylab)
elif c.get()==0:
c_label = ttk.Label(win, text="NotSet")
c_label.grid(column=xlab, row=ylab)
else:
c_label = ttk.Label(win, text=c.v.get())
c_label.grid(column=xlab, row=ylab)
# Changing the Label
ttk.Label(win, text="Enter a name:").grid(column=0, row=0)
# Adding a Textbox Entry widget
name = tk.StringVar()
name_entered = ttk.Entry(win, width=12, textvariable=name)
name_entered.grid(column=0, row=1)
# Adding a Button
action = ttk.Button(win, text="Click Me!", command=click_me)
action.grid(column=2, row=1)
# Creating three checkbuttons
ttk.Label(win, text="Choose a number:").grid(column=1, row=0)
number = tk.StringVar()
number_chosen = ttk.Combobox(win, width=12, textvariable=number, state='readonly')
number_chosen['values'] = (1, 2, 4, 42, 100)
number_chosen.grid(column=1, row=1)
number_chosen.current(0)
check1 = ChkBut("Button 1", 0, 4, 0, 5)
chVarUn = tk.IntVar()
check2 = tk.Checkbutton(win, text="UnChecked", variable=chVarUn)
check2.deselect()
check2.chVarUn = 0
check2.grid(column=1, row=4, sticky=tk.W)
chVarEn = tk.IntVar()
check3 = tk.Checkbutton(win, text="Enabled", variable=chVarEn)
check3.select()
check3.chVarEn = 0
check3.grid(column=2, row=4, sticky=tk.W)
name_entered.focus() # Place cursor into name Entry
#======================
# Start GUI
#======================
win.mainloop()
I can't generate the number because I get the error NameError: name 'z' is not defined.
import tkinter as tk
from random import randint
def randomize():
z.set ( randint(x.get(),y.get()))
root = tk.Tk()
x = tk.IntVar()
y = tk.IntVar()
text= tk.Label(root, text = "press the button for random number")
enterX = tk.Entry(root)
enterY = tk.Entry(root)
button = tk.Button(root, text = "Press here", command=randomize)
result = tk.Label(root,text="Number is:")
number = tk.Label(root, textvariable=z)
text.pack()
enterX.pack()
enterY.pack()
button.pack()
result.pack()
number.pack()
root.mainloop()
I need help to resolve the error
You have 2 problems here.
One. You are missing z = tk.Intvar() in the global namespace.
Two. You need to assign each entry field one of the IntVar()'s.
Keep in mind that you are not validating the entry fields so if someone types anything other than a whole number you will run into an error.
Take a look at this code.
import tkinter as tk
from random import randint
def randomize():
z.set(randint(x.get(),y.get()))
print(z.get()) # added print statement to verify results.
root = tk.Tk()
x = tk.IntVar()
y = tk.IntVar()
z = tk.IntVar() # added IntVar()
text= tk.Label(root, text = "press the button for random number")
enterX = tk.Entry(root, textvariable=x) # added textvariable
enterY = tk.Entry(root, textvariable=y) # added textvariable
button = tk.Button(root, text = "Press here", command=randomize)
result = tk.Label(root,text="Number is:")
number = tk.Label(root, textvariable=z)
text.pack()
enterX.pack()
enterY.pack()
button.pack()
result.pack()
number.pack()
root.mainloop()
I am trying to make a GUI where as soon as the user inputs an integer into a ttk.entry field, that many checkbuttons need to appear below it. For example, if they put "5" into the entry widget, 5 check buttons need to appear below the entry field.
Edit:
What I ended up using:
self.number_of_stages = tk.IntVar()
self.check_box_dict={}
self.num_of_stages={}
self.stagetempvar={}
self.equipment_widgets={}
def centrifugal_compressor_widgets(self):
self.equipment_widgets.clear()
self.equipment_widgets["NumOfStagesLabelCentComp"]=tk.Label(self.parent, text="Number of Stages:", bg="white")
self.equipment_widgets["NumOfStagesLabelCentComp"].place(relx=0.5, y=260, anchor="center")
self.equipment_widgets["NumOfStagesEntryCentComp"]=ttk.Entry(self.parent, textvariable=self.number_of_stages)
self.equipment_widgets["NumOfStagesEntryCentComp"].place(relx=0.5, y=290, anchor="center")
def OnTraceCentComp(self, varname, elementname, mode):
for key in self.check_box_dict:
self.check_box_dict[key].destroy()
try:
if self.number_of_stages.get() <=15 :
i=1
self.stagetempvar.clear()
while i <= self.number_of_stages.get():
self.stagetempvar[i]=tk.StringVar()
self.stagetempvar[i].set("Closed")
self.check_box_dict[i]=ttk.Checkbutton(self.parent, text=i, offvalue="Closed", onvalue="Open",variable=self.stagetempvar[i])
self.check_box_dict[i].place(relx=(i*(1/(self.number_of_stages.get()+1))), y=360, anchor="center")
i+=1
except:
pass
take a look at the below and let me know what you think...
A very ugly, super basic example:
from Tkinter import *
root = Tk()
root.geometry('200x200')
root.grid_rowconfigure(0, weight = 1)
root.grid_columnconfigure(0, weight = 1)
win1 = Frame(root, bg= 'blue')
win1.grid(row=0, column=0, sticky='news')
number = IntVar()
entry = Entry(win1, textvariable = number)
entry.pack()
confirm = Button(win1, text = 'Press to create widgets...', command = lambda:create_widgets(number.get()))
confirm.pack()
def create_widgets(number):
for n in range(0,number):
Checkbutton(win1, text = 'Checkbutton number : %s' % n).pack()
root.mainloop()
This should be a very very simple problem. I'm making a GUI in which I have multiple entry widgets... about 30 or so all in one column. Instead of making each box one by one it seems like a better idea to just generate the widgets with a loop. However, I'm finding it extremely difficult to .get() values from the entry widgets, and convert them into floats. This is what I have so far... any help would be greatly appreciated.
class Application(Frame):
def __init__(root,master):
Frame.__init__(root,master)
root.grid()
root.create_widgets()
def calcCR(root):
d1 = root.enter.get()
d1 = float(d1)
#root.answer.delete(0.0,END)
a = 'The C/R Alpha is! %lf \n' % (d1)
root.answer.insert(0.0, a)
def create_widgets(root):
### Generate Element List ###
for i in range(len(elem)):
Label(root, text=elem[i]).grid(row=i+1, column=0)
### Generate entry boxes for element wt% ###
for i in range(len(elem)):
enter = Entry(root, width = 8)
enter.grid(row = i+1,column=1)
enter.insert(0,'0.00')
root.button = Button(root, text = 'Calculate C/R', command = root.calcCR)
root.button.grid(row=11, column=2, sticky = W, padx = 10)
root.answer = Text(root, width = 50, height = 12.5, wrap = WORD)
root.answer.grid(row=1, column=2, rowspan = 10, sticky = W, padx = 10)
root = Tk()
root.title('C/R Calculator')
app = Application(root)
root.mainloop()
Put the Entry instances into a list.
from tkinter import Tk, Frame, Label, Entry, Button
class App(Frame):
def __init__(root, master):
Frame.__init__(root, master)
root.grid()
root.create_widgets()
def get_values(root):
return [float(entry.get()) for entry in root.entries]
def calc_CR(root):
answer = sum(root.get_values()) #Replace with your own calculations
root.answer.config(text=str(answer))
def create_widgets(root):
root.entries = []
for i in range(20):
label = Label(root, text=str(i))
label.grid(row=i, column=0)
entry = Entry(root, width=8)
entry.grid(row=i, column=1)
entry.insert(0, '0.00')
root.entries.append(entry)
root.calc_button = Button(root, text='Calculate C/R', command=root.calc_CR)
root.calc_button.grid(row=20, column=0)
root.answer = Label(root, text='0')
root.answer.grid(row=20, column=1)
def run(root):
root.mainloop()
root = Tk()
root.title('C/R Calculator')
app = App(root)
app.run()