I got a piece of code and I want to change it for my project, but I don't know how to get the value of my entries has a variable to be used in the start function. Here is my code:
#!/usr/bin/python3
import wiringpi
from time import sleep
gpio = wiringpi.GPIO(wiringpi.GPIO.WPI_MODE_GPIO)
shutterpin = 17
flashpin = 18
solenoidpin = 22
gpio.pinMode(shutterpin,gpio.OUTPUT)
gpio.pinMode(flashpin,gpio.OUTPUT)
gpio.pinMode(solenoidpin,gpio.OUTPUT)
wiringpi.pinMode(shutterpin,1)
wiringpi.pinMode(flashpin,1)
wiringpi.pinMode(solenoidpin,1)
from Tkinter import *
fields = 'size_drop1', 'interval_drop', 'size_drop2', 'lapse_before_flash', 'shutter_time'
def fetch(entries):
for entry in entries:
field = entry[0]
text = entry[1].get()
print('%s: "%s"' % (field, text))
def start(entries):
size_drop1 : float(size_drop1)
interval_drop : float(interval_drop)
size_drop2 : float(size_drop2)
lapse_before_flash : float(lapse_before_flash)
shutter_time : float(shutter_time)
sleep(lapse_before_flash)
gpio.digitalWrite(shutterpin,gpio.HIGH)
sleep(0.5)
gpio.digitalWrite(shutterpin,gpio.LOW)
gpio.digitalWrite(solenoidpin,gpio.HIGH)
sleep(size_drop1)
gpio.digitalWrite(solenoidpin,gpio.LOW)
gpio.digitalWrite(solenoidpin,gpio.HIGH)
sleep(interval_drop)
gpio.digitalWrite(solenoidpin,gpio.LOW)
gpio.digitalWrite(solenoidpin,gpio.HIGH)
sleep(size_drop2)
gpio.digitalWrite(solenoidpin,gpio.LOW)
sleep(lapse_before_flash)
gpio.digitalWrite(flashpin,gpio.HIGH)
sleep(0.5)
gpio.digitalWrite(flashpin,gpio.LOW)
def makeform(root, fields):
entries = []
for field in fields:
row = Frame(root)
lab = Label(row, width=15, text=field, anchor='w')
ent = Entry(row)
row.pack(side=TOP, fill=X, padx=5, pady=5)
lab.pack(side=LEFT)
ent.pack(side=RIGHT, expand=YES, fill=X)
entries.append((field, ent))
return entries
if __name__ == '__main__':
root = Tk()
ents = makeform(root, fields)
root.bind('<Return>', (lambda event, e=ents: fetch(e)))
b1 = Button(root, text='Show',
command=(lambda e=ents: fetch(e)))
b1.pack(side=LEFT, padx=5, pady=5)
b2 = Button(root, text='start', command=(lambda e=ents: start(e)))
b2.pack(side=LEFT, padx=5, pady=5)
b3 = Button(root, text='Quit', command=root.quit)
b3.pack(side=LEFT, padx=5, pady=5)
root.mainloop()
You seem to have the right idea on the fetch function part of your code, to access the typed text in a Entry Box on Tkinter, you can use the .get() function, like so:
# main tk window
root = Tk()
# creates the entry_box
entry_box = Entry(root, text='')
# places the entry_box on the program
entry_box.grid()
# changes the text, starting on the first char of the entry_box to 'test'
# (for testing purposes)
entry_box.insert(0, 'test')
# prints the typed test, in this case 'test'
print(entry_box.get())
# run the program
mainloop()
This will print the inserted string, just so you get the hang of it.
Also remember to assign the Entry to a variable, so you can call the .get() function.
Related
I am creating a Tkinter-based form where I want to store each item that the user types in as a separate variable. I understand how to generate the form, but I am lost on how to handle the program after the user presses the Enter button. I really just need everything stored as a string.
from tkinter import *
import pandas as pd
fields = ('Event', 'Event Folder', 'Session', 'Date: (MM/DD/YYYY)', 'StartTime: 24HR(HH:MM)', 'EndTime: 24HR(HH:MM)')
def saveVars(entries):
locals().update(entries)
return
def makeform(root, fields):
entries = {}
for field in fields:
row = Frame(root)
lab = Label(row, width=22, text=field+": ", anchor='w')
ent = Entry(row)
ent.insert(0,"")
row.pack(side = TOP, fill = X, padx = 5 , pady = 5)
lab.pack(side = LEFT)
ent.pack(side = RIGHT, expand = YES, fill = X)
entries[field] = ent
return entries
if __name__ == '__main__':
root = Tk()
ents = makeform(root, fields)
b1 = Button(root, text = 'Enter', command = lambda e = ents: saveVars(e))
b1.pack(side = LEFT, padx = 5, pady = 5)
root.mainloop()
What you need to do is build a function that does something with your entry fields. That said you may want to change up you code a little bit to make this easier. Instead of building your labels and entry fields in a function build them in the global namespace and then store the entry fields in a list.
import tkinter as tk
fields = ('Event', 'Event Folder', 'Session', 'Date: (MM/DD/YYYY)',
'StartTime: 24HR(HH:MM)', 'EndTime: 24HR(HH:MM)')
def do_something_with_entries():
for ndex, entry in enumerate(entry_list):
print(fields[ndex], ': ', entry.get())
if __name__ == '__main__':
root = tk.Tk()
entry_list = []
for field in fields:
row = tk.Frame(root)
lab = tk.Label(row, width=22, text=field + ": ", anchor='w')
ent = tk.Entry(row)
entry_list.append(ent)
row.pack(side='top', fill='x', padx=5, pady=5)
lab.pack(side='left')
ent.pack(side='right', expand='yes', fill='x')
tk.Button(root, text='Enter', command=do_something_with_entries).pack(side='left', padx=5, pady=5)
root.mainloop()
Results:
Here is an example using pandas:
import tkinter as tk
import pandas as pd
fields = ['Event', 'Event Folder', 'Session', 'Date: (MM/DD/YYYY)', 'StartTime: 24HR(HH:MM)', 'EndTime: 24HR(HH:MM)']
df = pd.DataFrame(columns=fields)
def do_something_with_entries():
global df
stored_values = []
for ndex, entry in enumerate(entry_list):
stored_values.append(entry.get())
series = pd.Series(stored_values, index=fields)
df = df.append(series, ignore_index=True)
if __name__ == '__main__':
root = tk.Tk()
entry_list = []
for field in fields:
row = tk.Frame(root)
lab = tk.Label(row, width=22, text=field + ": ", anchor='w')
ent = tk.Entry(row)
entry_list.append(ent)
row.pack(side='top', fill='x', padx=5, pady=5)
lab.pack(side='left')
ent.pack(side='right', expand='yes', fill='x')
tk.Button(root, text='Enter', command=do_something_with_entries).pack(side='left', padx=5, pady=5)
root.mainloop()
You are storing the questions as keys and Entry widgets as values of the entries dict.
Firstly, put the entries dict out of the makeform function (otherwise, only makeform function would be able to use it)
Secondly, create the answer dict. We are going to store the answers here.
Thirdly, create a fetch function which is to be called when the user clicks Enter button. It will go through the entries dict and set the values of the answers dict to the entered answers (using Entry.get(...) method)
Now you can process the form answers.
Here is an example:
from tkinter import *
import pandas as pd
fields = ('Event', 'Event Folder', 'Session', 'Date: (MM/DD/YYYY)',
'StartTime: 24HR(HH:MM)', 'EndTime: 24HR(HH:MM)')
entries = {}
answers = {}
def makeform(root, fields):
for field in fields:
row = Frame(root)
lab = Label(row, width=22, text=field + ": ", anchor='w')
ent = Entry(row)
row.pack(side=TOP, fill=X, padx=5, pady=5)
lab.pack(side=LEFT)
ent.pack(side=RIGHT, expand=YES, fill=X)
entries[field] = ent
return entries
def fetch():
for question in entries:
answers[question] = entries[question].get()
print(answers) # do something with the results now
if __name__ == '__main__':
root = Tk()
ents = makeform(root, fields)
root.bind('<Return>', fetch)
b1 = Button(root, text='Enter', command=fetch)
b1.pack(side=LEFT, padx=5, pady=5)
root.mainloop()
PS: You don't need to use a lambda-function as the button command. Simply use the fetch function as a command.
PS 1: And why do you call ent.insert(0, "")? It has no effect.
So I've been struggling with an issue for a week or so, been googling around trying to find different solutions, etc and getting nowhere. I was advised to put functioning code on here so I've cut it down some while still showing the issue.
I want to have a main page listing a set of goals, then if you click on the "Goal Entry" button up top a new window opens where you can input additional goals. Then you type in your desired additions, hit enter, and it adds it to the list on the main page.
I've accomplished all of the above EXCEPT, after you add the goals (and I have the list printing before and after so I know they're being added) and the entry window closes, the list of labels (created by an iteration) hasn't updated accordingly.
How do I get the list on the main page to automatically update when a new item is added to the list?
from tkinter import *
pg = ["goal1","goal2"]
pgtotal=1
psum=len(pg)
class yeargoals():
global pg, hg, fg, rg, rgtotal
def __init__(self,master):
self.master = master
master.title("This Year's Goals")
self.buttonframe = Frame(root)
self.buttonframe.pack(side=TOP, padx = 150, fill=BOTH)
self.home = Button(self.buttonframe, text="Home Page")
self.home.grid(row=1, column=1, padx=10)
self.enter = Button(self.buttonframe, text="Goal Entry", command=self.winenter)
self.enter.grid(row=1, column=2, padx=10)
self.finalize = Button(self.buttonframe, text="Finalize for Year")
self.finalize.grid(row=1, column=3, padx=10)
self.dashboard = Button(self.buttonframe, text="Goal Dashboard")
self.dashboard.grid(row=1,column=4, padx=10)
self.goalframe = Frame(root)
self.goalframe.pack(side=TOP, padx=150, pady=50, fill=BOTH, expand = True)
#Makes the label Fram I want the Checkboxes to go in
self.LabelFramep= LabelFrame(self.goalframe,text="Professional Goals")
self.LabelFramep.pack(side=LEFT, padx=10, anchor = N, fill=BOTH, expand = True)
#Makes the from the list above
for goal in pg:
l = Checkbutton(self.LabelFramep, text=goal, variable=Variable())
l.config(font=("Courier",12))
l.grid(sticky=W)
self.ptotal=Label(self.LabelFramep,text="Progress so far: "+str(pgtotal)+"/"+str(psum))
self.ptotal.config(font=("Courier",12))
self.ptotal.grid(sticky=W)
self.pper=Label(self.LabelFramep, text=str(round((pgtotal/psum)*100))+"% Complete")
self.pper.config(font=("Courier",12))
self.pper.grid(sticky=W)
def winenter(self):
global pg
self.winenter = Toplevel(root)
options = ["Professional", "Health", "Financial", "Reward Items"]
variable = StringVar(self.winenter)
variable.set(options[0])
#Title of entry section
t1 = Label(self.winenter, text="New Goal Entry")
t1.grid(row=0, column=1, columnspan=2)
#dropdown menu
d = OptionMenu(self.winenter, variable, *options)
d.grid(row=1, column=2)
#entry fields
e1 = Entry(self.winenter)
e1.grid(row=2, column=2, padx = 10, pady=5)
e2 = Entry(self.winenter)
e2.grid(row=3, column=2, padx=10, pady=5)
e3 = Entry(self.winenter)
e3.grid(row=4, column=2, padx=10, pady=5)
e4 = Entry(self.winenter)
e4.grid(row=5, column=2, padx=10, pady=5)
e5 = Entry(self.winenter)
e5.grid(row=6, column=2, padx=10, pady=5)
#Label for entry fields
l1 = Label(self.winenter, text="Goal Number 1")
l1.grid(row=2, column=1)
l2 = Label(self.winenter, text="Goal Number 2")
l2.grid(row=3, column=1)
l3 = Label(self.winenter, text="Goal Number 3")
l3.grid(row=4, column=1)
l4 = Label(self.winenter, text="Goal Number 4")
l4.grid(row=5, column=1)
l5 = Label(self.winenter, text="Goal Number 5")
l5.grid(row=6, column=1)
def enter():
global pg, main
print (pg)
if variable.get() == "Professional":
pg.append(e1.get())
self.winenter.destroy()
print (pg)
#Goal entry execute button
b = Button(self.winenter, text="Enter Goals", command=enter)
b.grid(row=7, column = 1)
root = Tk()
Window = yeargoals(root)
root.mainloop()
In your callback function to button "Enter Goals", you have done nothing to update your main window. Maybe you think the main window will magically keep updated with the variable pg, no, you need to do all those updates manually in your callback function.
For example, change your callback enter() to:
def enter():
global pg, main
print (pg)
if variable.get() == "Professional":
pg.append(e1.get())
l = Checkbutton(self.LabelFramep, text=pg[-1], variable=Variable())
l.config(font=("Courier",12))
l.grid(sticky=W)
self.winenter.destroy()
print (pg)
You can find the main window is updated after you click "Enter Goals".
I am developing a gui with text entry widgets that regenerate based on the number of a records in a table. I am using a list of fields that are each created as an entry widget. For at least one of these fields, I want to set up a combobox with values for the user to choose from. I've been playing around with adding a combobox to the root (I've just inserted a sample one for now) but it doesn't show up when I run the script. I don't get an error, the gui shows up with all the entry boxes, but not the combobox. Does anyone have any ideas: Here is some of the code:
import arcpy, tkMessageBox, ctypes, ttk
from Tkinter import *
mosaicD = r'C:\temp\temp.gdb\mapIndex_MD_test'
mapIndexTbl = r'C:\temp\temp.gdb\mapIndexTestTable'
formFields = ['County', 'Route', 'PMB', 'PME', 'Map_Sheet_Desc', 'HangingFileGroup', 'MapSubSet', 'MapSubSetStatus', 'Shtext', 'Status',
'SubStatus', 'MapDatum', 'Geo_Referenced_Datum', 'MapScale', 'CAD', 'DrawingDate', 'FileExtention','Original_MrSID_Filename']
fields = arcpy.ListFields(mapIndexTbl)
with arcpy.da.SearchCursor(mosaicD,'name') as cursorB:
for rowB in cursorB:
inputValues = []
def fetch(entries):
for entry in entries:
field = entry[0]
text = entry[1].get()
inputValues.append(text)
root.destroy()
def makeform(root, fields):
entries = []
for field in fields:
row = Frame(root)
lab = Label(row, width=20, text=field, anchor='w')
ent = Entry(row)
row.pack(side=TOP, fill=X, padx=5, pady=5)
lab.pack(side=LEFT)
ent.pack(side=RIGHT, expand=YES, fill=X)
entries.append((field, ent))
return entries
if __name__ == '__main__':
root = Tk()
root.iconbitmap(r'\\sv04docifs5\data5\vol2\Records\GIS\Logos\CT.ico')
root.geometry('375x650')
root.wm_title('Enter values for '+rowB[0])
cities = ('Toronto', 'Ottawa', 'Montreal', 'Vancouver', 'St. John')
cblist = Frame(root)
cbp3 = ttk.Labelframe(cblist, text='Pre-defined List')
cb3 = ttk.Combobox(cbp3, values=cities, state='readonly')
cb3.current(1) # set selection
cb3.pack(side=LEFT, expand=YES, fill=X)
# position and display
cbp3.pack(in_=cblist, side=TOP, pady=5, padx=10)
ents = makeform(root, formFields)
root.bind('<Return>', (lambda event, e=ents: fetch(e)))
b1 = Button(root, text='Submit',
command=(lambda e=ents: fetch(e)))
b1.pack(padx=5, pady=5,anchor=CENTER)
#b2 = Button(root, text='Quit', command=root.quit)
#b2.pack(side=LEFT, padx=5, pady=5)
root.mainloop()
The combobox cb3 is packed in the frame cbp3. That frame is packed in frame cblist. Nowhere do you call pack or grid on cblist. Since cblist is invisible, so are its children.
I've been trying to get my Tkinter dialog to do a simple date subtraction, but something is holding it up. The date subtraction seems to hold up when run from the shell, but I'm getting nothing from this is Tk.
The code is borrowed from another script that I have running successfully with all the form and windows setup.
#!/usr/bin/python
from Tkinter import *
import datetime
import math
fields = ('Enter Date (mm/dd/yy)', 'Days Since 10/30/14')
def Calc(entries):
d = raw_input(entries['Enter Date (mm/dd/yy)'].get())
nd = datetime.datetime.strptime(d, "%m/%d/%y").date()
d1 = "10/30/14"
od = datetime.datetime.strptime(d1, "%m/%d/%y").date()
diff = (nd - od).days
diff = ('%8.2f' % diff).strip()
entries['Days Since 10/30/14'].delete(0,END)
entries['Days Since 10/30/14'].insert(0, diff)
def makeform(root, fields):
root.title('Date Difference')
entries = {}
for field in fields:
row = Frame(root)
lab = Label(row, width=22, text=field+": ", anchor='w', font=('arial', 12))
ent = Entry(row, font=('arial', 12))
row.pack(side=TOP, fill=X, padx=5, pady=5)
lab.pack(side=LEFT, padx=10)
ent.pack(side=RIGHT, expand=YES, fill=X)
entries[field] = ent
return entries
if __name__ == '__main__':
root = Tk()
root.geometry("400x400+300+300")
ents = makeform(root, fields)
root.bind('<Return>', (lambda event, e=ents: Calc(e)))
b1 = Button(root, text='Calculate', font=('arial',12), command=(lambda e=ents: Calc(e)))
b1.pack(side=LEFT, padx=5, pady=5)
b2 = Button(root, text='Quit', font=('arial',12), command=root.quit)
b2.pack(side=LEFT, padx=5, pady=5)
root.mainloop()
Any help would be appreciated...
Even now I messed it up more, somehow it doesn't even start at all and highlights the "lab" variable under makeform(root,fields): it was running a minute ago, though would not do the calculation...
Help?
d = raw_input(entries['Enter Date (mm/dd/yy)'].get())
raw_input gets data from the user via the command line. Is that intentional? You don't need it if you just want to find what the user typed into the entry.
d = entries['Enter Date (mm/dd/yy)'].get()
I am new in python GUI. I was trying to get the value from 'abc' entry box. However, it can only get the default value (which is 58 now). If I change the value then it cannot get the changed (or current) value. Your input would be highly appreciated.
fields = ('abc', 'def', 'ghi','jkl')
def outputdata(master, fields):
entries = {}
helpLf = LabelFrame(master, text="2. Bill of Materials:")
helpLf.grid(row=0, column=9, columnspan=5, rowspan=8, \
sticky='NS', padx=5, pady=5)
for n in range(len(fields)):
lab = Label(helpLf, text= fields[n]+": ", anchor='w')
lab.grid(row=n, column=5, padx=5, pady=5)
ent = Entry(helpLf, bg="yellow")
ent.insert(0,"58")
ent.grid(row=n, column=7, padx=5, pady=5)
entries[fields[n]] = ent
return entries
if __name__ == '__main__':
master = Tk()
ents = outputdata(master, fields)
t = outputdata(master, fields)['abc'].get()
Button(master, text='Show me the BoM', command = (lambda e=ents:clamp_number(e))).grid(row=10, column=0, sticky=W, pady=4)
Without knowing what clamp_number is, I cannot comment on your code in particular.
But, if you want to know how to get the "current" value of a Entry widget, you will have to use a StringVar variable.
>>> from tkinter import Tk, StringVar, Entry
>>> root = Tk()
>>> sv = StringVar(root)
>>> entry = Entry(root, textvariable=sv)
>>> sv.get()
''
>>> entry.insert('insert', 'hello')
>>> sv.get()
'hello'
>>>
Whats happening here is, you are binding an Entry widget to a StringVar. You can call the StringVar's get() and set() methods as required.