Related
I'm aware that my code isn't very clean, , my primary focus at the moment is to make the program work.
I’m working with Tkinter and I created a search- and listbox based on a column in Excel. The Excelfile is imported by pandas, as a dataframe. The idea is that people can search for something (for example ‘Eiffel Tower’), that the value (‘Eiffel Tower’) is selected and that Python gives the construction date as output (so for example the year 1889) in the interface.
You search and make sure that the value is visible in the entrybox, and then you click on a button. After clicking on the button, you will see ‘1889’.
Both the buildings as the construction dates are listed in an Excelfile. Column A contains the buildings, column B contains the construction dates.
The search and listbox works. But I’m not ably to connect column A to column B, or to get an output based on the input that the uses gives.
The 'output_Startdate' was to test if the if-statement worked (what it does). The 'def connectie()' is me trying to find a solution.
My code:
import tkinter as tk
from tkinter import *
from tkinter import Listbox
from tkinter import ttk
import pandas as pd
interface = tk.Tk()
interface.configure(bg="#60c1c9")
interface.geometry('1500x750')
interface.title('Construction Dates')
title = Label(interface, text='1. BUILDINGS')
title.configure(bg="#60c1c9", fg="#000000", font=("Calibri", 20, "bold"))
title.place(relx=0.15, rely=0, anchor=N)
file_name = “List_Buildings.xlsx”
xl_workbook = pd.ExcelFile(file_name)
df = xl_workbook.parse(“Buildings”)
alist = df['MONUMENT'].tolist()
Startdate = df['Startdate'].tolist()
Enddate = df['Enddate'].tolist()
Label(
text="Select what you see on the picture.",
bg="#60c1c9",
fg="#000000",
font=("Calibri", 12)
).place(relx=0.29, rely=0.05, anchor=N)
def update(data):
my_list_1.delete(0, END)
for entry in data:
my_list_1.insert(END, entry)
def check(e):
typed = entry_1.get()
if typed == '':
data = alist
else:
data = []
for item in alist:
if typed.lower() in item.lower():
data.append(item)
update(data)
def fillout(e):
entry_1.delete(0, END)
entry_1.insert(0, my_list_1.get(ACTIVE))
entry_1 = Entry(interface, width=53)
entry_1.place(relx=0.205, rely=0.12, anchor=N)
entry_1.bind('<KeyRelease>', check)
my_list_1: Listbox = Listbox(interface, height=20, width=50)
my_list_1.place(relx=0.2, rely=0.15, anchor=N)
my_list_1.bind("<<ListboxSelect>>", fillout)
scrollbar_v = Scrollbar(interface, orient=VERTICAL, command=my_list_1.yview)
scrollbar_v.place(relx=0.301, rely=0.151, height=324)
scrollbar_h = Scrollbar(interface, orient=HORIZONTAL, command=my_list_1.xview)
scrollbar_h.place(relx=0.0985, rely=0.583, width=320.5)
#alist = df['MONUMENT'].tolist()
#output = df['Startdate'].tolist()
#df2 = pd.DataFrame(columns=['MONUMENT', 'Startdate', 'Enddate'])
#df2 = df.apply(lambda x: df['MONUMENT'] == df['Startdate'])
#print(df2)
def connectie():
value = entry_1.get()
for i in df['MONUMENT']:
if value == alist:
BLOCK_NAME.set(output)
return
def output_Startdate():
if entry_1.get() == ‘Eiffeltower’:
tekst = tk.Label(interface, text="good")
tekst.place(relx=0.3, rely=0.8)
else:
tekst = tk.Label(interface, text="this value doesn't excist")
tekst.place(relx=0.3, rely=0.8)
button = Button(interface, text='click here', command=output_Startdate)
button.place(relx=0.29, rely=0.7)
interface.mainloop()
I'm not sure what your data looks like (you didn't hand us a sample), so I hope I did it right. There are two parts to my answer, the first is for loading the file and setting the index column (I hope the names are all unique), and the second part is how to loc for the data you are looking for.
file_name = 'List_Buildings.xlsx' # file name
# read the file's Sheet1 and create dataframe with column 'MONUMENT' as index
df = pd.read_excel(file_name, 'Sheet1', index_col='MONUMENT')
# create alist from the index
alist = df.index.tolist()
def output_Startdate():
# get the entry_1 value
monument = entry_1.get()
# use monument (the entry_1 value) as index for dataframe loc and 'Startdate' as the column
start_date = df.loc[monument, 'Startdate']
# set the text for the label
tekst = tk.Label(interface, text=f"Start date: {start_date}")
tekst.place(relx=0.3, rely=0.8)
I am trying to make a weather forecast "app" using python, following the instructions of this video: https://www.youtube.com/watch?v=7JoMTQgdxg0
Everything works fine, except from the functionality of displaying some icons to make it look better.
If i remove the code that its used for the icons, everything works perfect. I don´t know what I should do so this works.
from tkinter import *
from tkinter import messagebox
from configparser import ConfigParser
import requests
url = "https://api.openweathermap.org/data/2.5/weather?q={}&appid={}"
config_file = 'config.ini'
config = ConfigParser()
config.read(config_file)
api_key = config['api_key']['key']
def get_weather(city):
result = requests.get(url.format(city, api_key))
if result:
#print(result.content)
json = result.json()
#City, country, temp_celsius, temp:farenheit, icon weather
city = json['name']
country = json['sys']['country']
temp_kelvin = json['main']['temp']
temp_celsius = temp_kelvin - 273.15
temp_farenheit = (temp_kelvin - 273.15) * 9 / 5 + 32
icon = json['weather'][0]['icon']
weather = json['weather'][0]['main']
final = (city, country, temp_celsius, temp_farenheit, icon, weather)
return final
else:
return None
#print(get_weather('London'))
def search():
city = city_text.get()
weather = get_weather(city)
if weather:
location_lbl['text'] = '{}, {}'.format(weather[0], weather[1])
image['bitmap'] = 'weather_icons/{}.png'.format(weather[4])#HERE ITS THE PROBLEM
temp_lbl['text'] = '{:.2f}ºC, {:.2f}ºF'.format(weather[2], weather[3])
weather_lbl['text'] = weather[5]
else:
messagebox.showerror('Error', 'Cannot find city {}'.format(city))
app = Tk()
app.title("Weather App")
app.geometry('700x350')
city_text = StringVar()
city_entry = Entry(app, textvariable=city_text)
city_entry.pack()
search_btn = Button(app, text='Search Weather', width=12, command=search)
search_btn.pack()
location_lbl = Label(app, text="", font=('bold', 20))
location_lbl.pack()
image = Label(app, bitmap='')#HERE ITS THE PROBLEM
image.pack()
temp_lbl = Label(app, text="")
temp_lbl.pack()
weather_lbl = Label(app, text="")
weather_lbl.pack()
app.mainloop()
I also have another file that its called: config.ini for saving my API key, and a folder named weather_icons for storing the images
.
I have been building a flashcard app and have run into a roadblock while trying to implement a radiobutton. The issue is when run the menu shows up and your able to access the lesson, but the radiobuttons do not appear. Whenever the code is run this error shows up TypeError: string indices must be integers attached to the radiobutton functionbalancing_radio_butto1 = Radiobutton(balancing_frame, text = balancing[answer_list[0]], variable=balancing_radio, value = 1) if someone could explain the why this error shows up as well as how to fix it it would be much appreciated. Below is my code that I have so far.
from tkinter import *
from PIL import ImageTk, Image
from random import branding
import random
root = Tk()
root.title('Chemistry Flashcards')
root.geometry("500x500")
def balancing():
balancing_frame.pack(fill="both", expand=1)
global show_balancing
show_balancing = Label(balancing_frame)
show_balancing.pack(pady=15)
global balancing
balancing = ['balanced1', 'balanced2', 'balanced3', 'balanced4', 'balanced5', 'unbalanced1', 'unbalanced2', 'unbalanced3', 'unbalanced4', 'unbalanced5']
global balancing_state
balancing_state = {
'balanced1':'balanced',
'balanced2':'balanced',
'balanced3':'balanced',
'balanced4':'balanced',
'balanced5':'balanced',
'unbalanced1':'unbalanced',
'unbalanced2':'unbalanced',
'unbalanced3':'unbalanced',
'unbalanced4':'unbalanced',
'unbalanced5':'unbalanced',
}
answer_list = []
count = 1
while count < 3:
rando = randint(0, len(balancing_state)-1)
if count == 1:
answer = balancing[rando]
global balancing_image
balancing = "C:/Users/Kisitu/Desktop/project/balancing/" + balancing[rando] + ".png"
balancing_image = ImageTk.PhotoImage(Image.open(balancing))
show_balancing.config(image=balancing_image)
answer_list.append(balancing[rando])
'''random.shuffle(balancing)'''
count += 1
random.shuffle(answer_list)
global balancing_radio
balancing_radio = IntVar()
balancing_radio_butto1 = Radiobutton(balancing_frame, text = balancing[answer_list[0]], variable=balancing_radio, value = 1)
balancing_radio_butto1.pack(pady=10)
balancing_radio_butto2 = Radiobutton(balancing_frame, text = balancing[answer_list[1]], variable=balancing_radio, value = 2).pack()
my_menu = Menu(root)
root.config(menu=my_menu, bg='#B7F7BB')
lesson_menu = Menu(my_menu)
my_menu.add_cascade(label="Lesson", menu=lesson_menu)
lesson_menu.add_command(label="balancing", command=balancing)
lesson_menu.add_separator()
lesson_menu.add_command(label="Exit", command=root.quit)
balancing_frame = Frame(root, width=500, height=500, )
root.mainloop()
... text = balancing[answer_list[0]] ...
balancing is a list, you are trying to index a value from the list.
you are passing answer_list[0] as index.
answer_list contains random strings from balancing.
you are trying to index a list with a string like in
balancing["balanced2"]
maybe you could use a dictionary?
I want to validate two tkinter entries. One called minimum and the other called maximum. Of course, I want to make sure that minimum does not exceed maximum. And there is a third entry called increment which has to be lesser than maximum. There are a set of 15 such entries which I am trying to validate.
I have tried using for loop and tracing the textvariable of each entry. But inside the for loop, I am able to validate only a single entry box. Also, when I skip the validation for that specific one entry called the txtCab, it throws the following exception: If I do it for all the widgets, it does work, but fails some times.
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\beejb\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "C:\PROSAIL_5B_Fortran\PROSAIL_5B_FORTRAN\PROSAIL.py", line 191, in min_max
minVar = eval("self.txtVar_"+ str(wid)+ "_min.get()")
File "<string>", line 1, in <module>
NameError: name 'self' is not defined
The validation function I have used is:
def min_max(*args):
alltextFields = ["N","Cab","Car","Cw","Cm","Cbrown", "rsoil0","LIDFa","LIDFb","TypeLIDF","LAI","hspot","tts","tto","psi" ]
for wid in alltextFields:
if eval("self." + wid + "_variable.get()"):
minVar = eval("self.txtVar_"+ str(wid)+ "_min.get()")
maxVar = eval("self.txtVar_"+ str(wid) + "_max.get()")
rangeVar = eval("self.txtVar_"+ str(wid) + "_range.get()")
##
## print((minVar))
## print((maxVar))
## print((rangeVar))
if len(minVar) > 0 and len(maxVar):
if (minVar) > (maxVar):
messagebox.showinfo("Input Error", "Minimum should not be greater than maximum")
if len(rangeVar) > 0 and len(maxVar) > 0:
if (rangeVar) > (maxVar) :
messagebox.showinfo("Input Error", "Increment cannot exceed maximum limit")
## print(self.txtVar_Cab_min.get()); print(self.txtVar_Cab_max.get());
## print(self.txtVar_N_min.get()); print(self.txtVar_N_max.get());
if len(self.txtVar_Cab_min.get()) > 0 and len(self.txtVar_Cab_max.get()) > 0 and len(self.txtVar_Cab_range.get()) > 0:
if (self.txtVar_Cab_min.get()) > (self.txtVar_Cab_max.get()):
messagebox.showinfo("Input Data Error", "Minimum should not be greater than maximum!!")
if (self.txtVar_Cab_range.get()) > (self.txtVar_Cab_max.get()):
messagebox.showinfo("Error", "Increment cannot exceed maximum!!")
Another validation function I have tried is:
def validateMRM(self,value, text,W):
vMin,vMax,vRange;
entry = self.controller.nametowidget(W)
print(entry)
if entry == self.txt_N_min:
print(entry.get())
print(self.txtVar_N_max.get())
print(self.txtVar_N_range.get())
alltextFields = ["txt_N","txt_Cab","txt_Car","txt_Cab","txt_Cw","txt_Cw","txt_Cm","txt_Cbrown","txt_Cm", "txt_rsoil0",
"txt_LIDFa","txt_LIDFb","txt_TypeLIDF","txt_LAI","txt_hspot","txt_hspot","txt_tts","txt_tto","txt_psi"
]
for wid in alltextFields:
typeOfVar = wid.split("_")
if entry == eval("self.txt_" + str(typeOfVar[1])+ "_min"):
vMin = eval("self.txtVar_" + str(typeOfVar[1])+ "_min.get()")
print(eval("self.txtVar_" + str(typeOfVar[1])+ "_min.get()"))
vMax = eval("self.txtVar_" + str(typeOfVar[1])+ "_max.get()")
print(eval("self.txtVar_" + str(typeOfVar[1])+ "_max.get()"))
vRange = eval("self.txtVar_" + str(typeOfVar[1])+ "_range.get()")
print(eval("self.txtVar_" + str(typeOfVar[1])+ "_range.get()"))
print(vMin); print(vMax); print(vRange)
if len(vMin) > 0 and len(vMax) > 0 and len(vRange) > 0:
if (vMin) > (vMax):
messagebox.showinfo("Error", "Minimum cannot be greater than maximum")
if (vRange) > (vMax) :
messagebox.showinfo("Error", "Increment cannot exceed the maximum limit")
print(len(entry.get()))
if len(entry.get())>2:
And here is how all the entries are created:
self.lbl_N = tk.Label(self,text="Structure Coefficient(N)",anchor="w",width=40,bg='white'); self.lbl_N.grid(row=3,column=4,padx=4,pady=4);
self.N_variable = tk.BooleanVar()
self.chk_N = tk.Checkbutton(self,variable=self.N_variable, command=lambda:self.show_hide()); self.chk_N.grid(row=3,column=6,padx=4,pady=4);
self.txt_N = tk.Entry(self,width=10,validate = 'key', validatecommand = vcmd); self.txt_N.grid(row=3,column=7,padx=4,pady=4);
self.txtVar_N_min = tk.StringVar(); self.txtVar_N_max = tk.StringVar(); self.txtVar_N_range = tk.StringVar();
self.txtVar_N_min.trace("w", min_max); self.txtVar_N_max.trace("w", min_max); self.txtVar_N_range.trace("w", min_max);
self.txt_N_min = tk.Entry(self,width=5,validate = 'key',textvariable=self.txtVar_N_min, validatecommand = vcmd_min_max);
self.txt_N_max = tk.Entry(self,width=5,validate = 'key', textvariable=self.txtVar_N_max,validatecommand = vcmd_min_max);
self.txt_N_range = tk.Entry(self,width=5,validate = 'key', textvariable=self.txtVar_N_range,validatecommand = vcmd_min_max);
There are a set of fourteen such entries and I need to validate each of them.
But none of this gives the actual output I want. It works some time and fails some other times.
I am not sure why is that happening and I have spent a hell of time with this validation.
I'm not sure whether this answers your question but it should point you in the right direction.
I couldn't make much sense of your code. I've produced a 15 row x 4 column grid.
The 4th column is a message that the 3 fields next to it are 'OK' or if not indicate the problem. The validation is run on the whole grid for each keypress. If this is too slow a validate button could launch the validation instead.
import tkinter as tk
from tkinter import ttk
def rec(): return {'lo': 0, 'hi': 0, 'step': 0, 'ok': '' }
root = tk.Tk()
root.title('SO Question')
def entry(id, ent_dict, var_dict, v=0):
""" Add an Entry Widget to the root, with associated StringVar."""
var_dict[id] = tk.StringVar()
var_dict[id].set(str(v))
ent_dict[id] = ttk.Entry(root, textvariable= var_dict[id], width = 10 )
return ent_dict[id]
def do_validate(lo, hi, step):
""" Return OK if lo, hi and step are consistent else an error string. """
if lo < hi and step < hi: return 'OK'
txt = ''
if lo >= hi:
txt = 'lo >= hi. '
if step >= hi:
txt += 'step >= hi.'
return txt
def conv(txt):
""" Convert text to float. Return 0.0 if not valid float e.g "" or 'a' """
try:
return float(txt)
except ValueError:
return 0.0
def oklabel(ent_dict, var_dict):
""" Add an OK Label to a row. """
lo = conv(var_dict['lo'].get())
hi = conv(var_dict['hi'].get())
step = conv(var_dict['step'].get())
var_dict['ok'] = tk.StringVar()
var_dict['ok'].set(do_validate(lo, hi, step))
ent_dict['ok'] = ttk.Label(root, textvariable = var_dict['ok'], width = -17)
return ent_dict['ok'] # Return the Label object for gridding.
def do_check(*args):
""" Loop through the rows setting the validation string in each one. """
for var_dict in stringvars:
lo = conv(var_dict['lo'].get())
hi = conv(var_dict['hi'].get())
step = conv(var_dict['step'].get())
var_dict['ok'].set(do_validate(lo, hi, step))
# Add column labels
ttk.Label(root, text='Minimums').grid(row=0, column=0)
ttk.Label(root, text =' Maximums').grid(row=0, column=1)
ttk.Label(root, text='Increment').grid(row=0, column=2)
ttk.Label(root, text='Valid').grid(row=0, column=3)
# Create containers for he Entries and Stringvars
entries =[]
stringvars = []
# Add 15 rows of Entries / Validation Labels to the UI.
for row in range(1, 16):
tempe=rec()
tempv=rec()
entry('lo', tempe, tempv, 0).grid(row = row, column=0)
entry('hi', tempe, tempv, 0).grid(row = row, column=1)
entry('step', tempe, tempv, 0).grid(row = row, column=2)
oklabel(tempe, tempv).grid(row = row, column = 3)
entries.append(tempe)
stringvars.append(tempv)
# Bind do_check to all Entry widgets.
root.bind_class('TEntry', '<KeyPress>', do_check, add='+')
root.bind_class('TEntry', '<BackSpace>', do_check, add='+')
root.bind_class('TEntry', '<Delete>', do_check, add='+')
root.mainloop()
In the past I've got stuck trying to validate multiple fields by not allowing inconsistent entries. It is difficult for users to follow what is required to correct fields. They have to work in the correct order. e.g. lo = 100, hi = 9, and step = 1. Should the UI allow the last zero in 100 to be deleted, leaving 10 which is gt 9?
This could be extended to activate a 'Next' button only if all rows are OK.
Edit 1 - Response to Comment
This has a function to create and activate each row of the display. Each row has it's own variables and checking function. They are triggered by the trace on the three Entry StringVars, there's no need to use validate.
import tkinter as tk
from tkinter import ttk
def to_float(txt):
""" Safely convert any string to a float. Invalid strings return 0.0 """
try:
return float(txt)
except ValueError:
return 0.0
def row_n( parent, n, init_show = 0 ):
""" Create one row of the display. """
# tk.Variables
v_show = tk.IntVar()
v_min = tk.StringVar()
v_max = tk.StringVar()
v_incr = tk.StringVar()
v_message = tk.StringVar()
# Initialise variables
v_min.set('0')
v_max.set('1')
v_incr.set('1') # Can the increment be zero?
v_show.set(init_show)
v_message.set("OK")
def do_trace(*args):
""" Runs every time any of the three Entries change value.
Sets the message to the appropriate text.
"""
lo = to_float(v_min.get())
hi = to_float(v_max.get())
inc = to_float(v_incr.get())
if lo < hi and inc <=hi:
v_message.set('OK')
else:
txt = ''
if lo >= hi:
txt += 'Min >= Max'
if inc > hi:
if len(txt): txt += ' & '
txt += 'Incr > Max'
v_message.set(txt)
# Set trace callback for changes to the three StringVars
v_min.trace('w', do_trace)
v_max.trace('w', do_trace)
v_incr.trace('w', do_trace)
def activation(*args):
""" Runs when the tickbox changes state """
if v_show.get():
e_min.grid(row = n, column = 1)
e_max.grid(row = n, column = 2)
e_inc.grid(row = n, column = 3)
message.grid(row = n, column = 4)
else:
e_min.grid_remove()
e_max.grid_remove()
e_inc.grid_remove()
message.grid_remove()
tk.Checkbutton(parent,
text = 'Structure Coefficient {} :'.format(n),
variable = v_show, command = activation ).grid(row = n, column = 0)
e_min = tk.Entry(parent, width=5, textvariable = v_min)
e_max =tk.Entry(parent, width=5, textvariable = v_max)
e_inc = tk.Entry(parent, width=5, textvariable = v_incr)
message = tk.Label(parent, width=-15, textvariable = v_message)
activation()
return { 'Min': v_min, 'Max': v_max, 'Inc': v_incr }
def show_results():
print('Min Max Inc')
for row in rows:
res = '{} {} {}'.format(row['Min'].get(), row['Max'].get(), row['Inc'].get())
print( res )
root = tk.Tk()
root.title('SO Question')
ttk.Label(root, text='Minimums').grid(row=0, column=1)
ttk.Label(root, text =' Maximums').grid(row=0, column=2)
ttk.Label(root, text='Step', width = 5 ).grid(row=0, column=3)
ttk.Label(root, text='Valid', width = 15 ).grid(row=0, column=4)
rows = []
for r in range(1,16):
rows.append(row_n(root, r, init_show=r%3 == 0 ))
tk.Button(root, command=show_results, text = ' Show Results ').grid(column=1, pady = 5)
root.mainloop()
This is another approach. Does this help.
Here's another suggestion. Incorporate the Label and Entry in the row-n function. Include activating / disabling the Entry in the activate function. The row_n function is executed in a loop through a list of the descriptions you want.
import tkinter as tk
row_names = [ "Structure Coefficient(N)", "Chlorophyll Content(Cab) (µg.cm-2)",
"Carotenoid content(Car) (µg.cm-2)", "Brown pigment content(Cbrown)(arbitrary units)"]
def row_n(parent, desc, n, init_show = 0 ):
""" Create one row of the display. """
# tk.Variables
v_show = tk.IntVar()
v_min = tk.StringVar()
v_max = tk.StringVar()
v_incr = tk.StringVar()
v_fixed = tk.StringVar() # New StringVar
v_message = tk.StringVar()
v_show.set(init_show)
v_message.set("OK")
def do_trace(*args):
""" Runs every time any of the three Entries change value.
Sets the message to the appropriate text.
"""
lo = to_float(v_min.get())
hi = to_float(v_max.get())
inc = to_float(v_incr.get())
if lo < hi and inc <=hi:
v_message.set('OK')
else:
txt = ''
if lo >= hi:
txt += 'Min >= Max'
if inc > hi:
if len(txt): txt += ' & '
txt += 'Incr > Max'
v_message.set(txt)
# Set trace callback for changes to the three StringVars
v_min.trace('w', do_trace)
v_max.trace('w', do_trace)
v_incr.trace('w', do_trace)
def activation(*args):
""" Runs when the tickbox changes state """
if v_show.get():
e_min.grid(row = n, column = 8)
e_max.grid(row = n, column = 9)
e_inc.grid(row = n, column = 10)
message.grid(row = n, column = 11)
e_fixed.config(state = 'disabled') # Disable the base Entry
else:
e_min.grid_remove()
e_max.grid_remove()
e_inc.grid_remove()
message.grid_remove()
e_fixed.config(state = 'normal') # Enable the base Entry Widget
tk.Label(parent, text = desc ).grid(row = r+1, column = 4 ) # Add the desc. Label
e_fixed = tk.Entry(parent, textvariable = v_fixed) # Add the new Entry widget
e_fixed.grid(row = r+1, column = 5)
tk.Checkbutton(parent,
text = ' '.format(n),
variable = v_show, command = activation ).grid(row = n, column = 6)
e_min = tk.Entry(parent, width=5, textvariable = v_min)
e_min.config(font=('Candara', 15))
e_max =tk.Entry(parent, width=5, textvariable = v_max)
e_max.config(font=('Candara', 15))
e_inc = tk.Entry(parent, width=5, textvariable = v_incr)
e_inc.config(font=('Candara', 15))
message = tk.Label(parent, width=-15, textvariable = v_message)
message.config(font=('Candara', 15))
activation()
return { 'Min': v_min, 'Max': v_max, 'Inc': v_incr, 'Fixed': v_fixed }
# The 'Fixed' field added to the dictionary to return
def print_row(row):
fmt = 'Min: {}, Max: {}, Inc: {}, Fixed: {}'
print(fmt.format(
row['Min'].get(), row['Max'].get(), row['Inc'].get(), row['Fixed'].get()
))
def to_float(txt):
""" Safely convert any string to a float. Invalid strings return 0.0 """
try:
return float(txt)
except ValueError:
return 0.0
# GUI Start
root = tk.Tk()
root.title('Validation wth Trace')
# Header Labels
tk.Label(root,text="Min").grid(row=0,column=8,padx=4,pady=4)
tk.Label(root,text="Max").grid(row=0,column=9,padx=4,pady=4)
tk.Label(root,text="Inc").grid(row=0,column=10,padx=4,pady=4)
# Body of rows
rows = []
for r, r_text in enumerate(row_names):
rows.append(row_n( root, r_text, r+1))
root.mainloop()
print("Strings in the Entry fields")
for r, row in enumerate(rows):
print('Row: ', r, 'Data:', end=' ')
print_row(row)
HTH. Seeing your code in the inked question you may prefer to make row_n a class.
I am trying to let the user add three entries and the code will use them to get data from an API and then export the data to CSV. I am trying to do it like this but I am not sure what is the issue and I am still new on Tkinter.
from Tkinter import *
import sys
import csv
from urllib import urlopen
import json
from dateutil.relativedelta import relativedelta
from datetime import datetime
import pandas as pd
root = Tk()
start2 = StringVar()
end2 = StringVar()
root.geometry("1600x800+0+0")
root.title("Data")
startd = "2017-13-03"
endd = "2017-13-03"
power1 =""
ID = "1232.4343.323"
class data1:
def __init__(self,master):
frame = Frame(master)
#frame.pack()
Tops = Frame(root, width=1600, height=1000, bg="powder blue")
Tops.pack(side=TOP)
self.output()
thelabel = Label(Tops, text="Data",font =('arial',30))
thelabel.pack(side=TOP)
def output(self):
Label(text='Start Date:',font=('arial', 12, 'bold')).pack(side=LEFT,padx=12,pady=12)
self.startd = Entry(root, width=10)
self.startd.pack(side=LEFT,padx=2,pady=16)
Label(text='End Date:',font=('arial', 12, 'bold')).pack(side=LEFT,padx=12,pady=12)
self.endd = Entry(root, width=10)
self.endd.pack(side=LEFT,padx=2,pady=16)
Label(text='Device ID:',font=('arial', 12, 'bold')).pack(side=LEFT,padx=12,pady=12)
self.ID = Entry(root, width=10)
self.ID.pack(side=LEFT,padx=2,pady=16)
self.b = Button(root, text='Submit', command=self.getjsondata)
self.b.pack(side=LEFT,padx=20,pady=5)
def getjsondata(self):
global power1
url1 = "https://api.data.com/mongo/measures/"+ID+"/"+startd+"/"+endd+"/?format=json"
power1 = urlopen(url1).read()
power1 = json.loads(power1)
power11 = pd.DataFrame(power1)
power11.csv(power11, file="MyData.csv")
b = data1(root)
root.mainloop()
The data comes in a json format and this is how the data comes:
[{"timestamp":"2017-01-14T19:47:00Z","value":"423"},{"timestamp":"2017-01-14T19:47:30Z","value":"419"},{"timestamp":"2017-01-14T19:48:00Z","value":"431"},{"timestamp":"2017-01-14T19:48:30Z","value":"429"},{"timestamp":"2017-01-14T19:49:00Z","value":"422"},{"timestamp":"2017-01-14T19:49:30Z","value":"427"},{"timestamp":"2017-01-14T19:50:00Z","value":"426"},{"timestamp":"2017-01-14T19:50:30Z","value":"427"},{"timestamp":"2017-01-14T19:51:00Z","value":"428"},{"timestamp":"2017-01-14T19:51:30Z","value":"426"},{"timestamp":"2017-01-14T19:52:00Z","value":"424"},{"timestamp":"2017-01-14T19:52:30Z","value":"423"},{"timestamp":"2017-01-14T19:53:00Z","value":"453"},{"timestamp":"2017-01-14T19:53:30Z","value":"433"},{"timestamp":"2017-01-14T19:54:00Z","value":"445"},{"timestamp":"2017-01-14T19:54:30Z","value":"438"},{"timestamp":"2017-01-14T19:55:00Z","value":"430"},{"timestamp":"2017-01-14T19:55:30Z","value":"437"},{"timestamp":"2017-01-14T19:56:00Z","value":"425"},{"timestamp":"2017-01-14T19:56:30Z","value":"420"},{"timestamp":"2017-01-14T19:57:00Z","value":"431"},{"timestamp":"2017-01-14T19:57:30Z","value":"435"},{"timestamp":"2017-01-14T19:58:00Z","value":"443"},{"timestamp":"2017-01-14T19:58:30Z","value":"430"},{"timestamp":"2017-01-14T19:59:00Z","value":"425"},{"timestamp":"2017-01-14T19:59:30Z","value":"406"},{"timestamp":"2017-01-14T20:00:00Z","value":"412"},{"timestamp":"2017-01-14T20:00:30Z","value":"417"},{"timestamp":"2017-01-14T20:01:00Z","value":"422"},{"timestamp":"2017-01-14T20:01:30Z","value":"422"},{"timestamp":"2017-01-14T20:02:00Z","value":"418"},{"timestamp":"2017-01-14T20:02:30Z","value":"415"},{"timestamp":"2017-01-14T20:03:00Z","value":"423"},{"timestamp":"2017-01-14T20:03:30Z","value":"411"},{"timestamp":"2017-01-14T20:04:00Z","value":"413"}]
I have filtered the data using panadas, my main issue is how to link an entry to a variable that I could use in my code. The entries are:
ID:
Starting date:
Ending date:
Please let me know what is the issue in my code.On the other hand I am planing to give the user the open in where to save the csv file on his computer if that is possible.
Thanks in advance
If problem is on pandas side:
It seems you need read_json and then if need select data by timestamps use loc:
df = pd.read_json(url1).set_index('timestamp')
print (df)
value
timestamp
2017-01-14 19:47:00 423
2017-01-14 19:47:30 419
2017-01-14 19:48:00 431
2017-01-14 19:48:30 429
...
...
date = pd.to_datetime('2017-01-14 19:47:00')
var = df.loc[date, 'value']
print (var)
423