dictionary which depends on 2nd dropbox selection with tkinter - python

from tkinter import *
import tkinter as tk
from tkinter import ttk
window=Tk()
window.title("RBEE Model")
window.geometry('500x450')
label7=Label(window,text='Select Pollutant:',fg='black',font=('Arial',14))
label7.grid(row=1,column=0,padx=5,pady=10)
Pollutant = ["PM2.5","PM10"]
crop_poll = [{'Rice':55,'Wheat':66,'Total Pulses':89,'Total Nine Oilseeds':69},
{'Total Pulses':89,'Total Nine Oilseeds':69}]
crop_poll_roll = ttk.Combobox(window, width=27, value=(Pollutant))
crop_poll_roll2 = ttk.Combobox(window, width=27, value=(crop_poll))
crop_poll_roll.grid(row=1, column=1, columnspan=2, padx=5, pady=10, sticky='w')
def callback2(eventObject2):
abcd = eventObject2.widget.get()
crop_p = crop_poll_roll.get()
index1=Pollutant.index(crop_p)
crop_poll_model.config(values=list(crop_poll[index1].keys()))
# crop_poll_model = ttk.Combobox(window, width=27,values=list(crop_poll[index1].keys()))
crop_poll_model = ttk.Combobox(window, width=27)
crop_poll_model.grid(row=2, column=1, columnspan=2, padx=5, pady=10, sticky='w')
crop_poll_model.bind('<Button-1>', callback2)
def emissions():
crop_p = crop_poll_roll.get()
index1=Pollutant.index(crop_p)
# crop_i=crop_poll_model.get()
# index2=crop_poll_model.index(crop_i)
# blank.delete(0, tk.END)
emiss= float((list(crop_poll[index1].values()))[index1])
# blank.insert(0, emiss)
emptylabel.config(text='Emissions:'+ str(emiss))
# blank = tk.Entry(window)
button1=Button(window,command=emissions,text='Calculate Emissions',fg='red',font=('Arial',14))
button1.grid(row=11,column=1)
emptylabel=Label(window,fg='green',font=('Arial',14))
emptylabel.grid(row=12,column=1,pady=10)
window.mainloop()
This code is working fine I just want to access the value of a dictionary within the list.enter image description here
I have attached the pic of the output here if I select the PM2.5 then I can choose another dropdown list.
so I select rice I want to display the square root of the value 55.
if I select wheat same thing I want to do with value 66 and so on.

You only have two values: "PM2.5"(index1=0) and "PM10"(index1=1).
When you execute this line of code,
emiss= float((list(crop_poll[index1].values()))[index1])
it means:
emiss= float((list(crop_poll[0].values()))[0])
or
emiss= float((list(crop_poll[1].values()))[1])
These are 'Rice': 55 in the first dictionary and 'Total Nine Oilseeds':69 in the second dictionary.
You can get the desired value from the dictionary like this:
import math
def emissions():
crop_p = crop_poll_roll.get()
index1=Pollutant.index(crop_p)
# Option 1
# string, dictionary key
selected_crop_value = crop_poll_model.get()
print(f"selected_crop_value: {selected_crop_value}")
# get value in dict by key
emiss= float(crop_poll[index1][selected_crop_value])
# Option 2
# integer, index in dropdown list
selected_crop_index = crop_poll_model.current()
print(f"selected_crop_index: {selected_crop_index}")
# get the value by the index of its key
# since version 3.6+, Python dictionaries are ordered
emiss= float(list(crop_poll[index1].values())[selected_crop_index])
emiss_sqrt = math.sqrt(emiss)
emptylabel.config(text='Emissions:'+ str(emiss_sqrt))
See also ttk.Combobox widget methods:
Python documentation
Combobox - Tcl/Tk version 8.5 (Newer versions of Python use version 8.6, but this link is helpful too).
You can also use the combobox event:
crop_poll_roll.bind('<<ComboboxSelected>>', callback)
For example, create a callback function for crop_poll_roll in which you change the state of crop_poll_model depending on whether you select "PM2.5" or "PM10".

Related

How to display the label ( text) value dynamically based on combo box selection value ( List box) in Tkinter?

I am new to tkinter application. The below code is working fine. Please help how to implement mentioned features.
The dynamic value should be displayed above clear button or below the combo box ( Used pack is bottom )- Now working
Clear the label value on combo box selection.
import tkinter as tk
from tkinter import ttk
from tkinter import *
from datetime import datetime
# root window
root = tk.Tk()
root.geometry("500x350")
root.resizable(False, False)
root.title('Test')
# Log Generator in frame
Generator = tk.Frame(root)
Generator.pack(padx=10, pady=10, fill='x', expand=True)
def clear():
combo.set('')
# Function to print the index of selected option
# in Combobox
def get_log_file_name(*arg):
date_Value = datetime.now().strftime("%Y_%m_%d_%I%M%S")
output_file_name_value = "Log_"+date_Value
if var.get() == "apple":
Label(Generator, text="The value at index: "+output_file_name_value+".txt", font=('Helvetica 12')).pack()
else:
Label(Generator, text="The value at index: "+output_file_name_value+".html", font=('Helvetica 12')).pack()
# Define Tuple of months
months = ('apple','banana')
# Create a Combobox widget
label = ttk.Label(Generator, text="Selection_Option:",font=('Helvetica', 10, 'bold'))
label.pack(fill='x', expand=True)
var = StringVar()
combo = ttk.Combobox(Generator, textvariable=var)
combo['values'] = months
combo['state'] = 'readonly'
combo.pack(padx=5, pady=5)
# Set the tracing for the given variable
var.trace('w', get_log_file_name)
# Create a button to clear the selected combobox
# text value
button = Button(Generator, text="Clear", command=clear)
button.pack(side=left)
# Make infinite loop for displaying app on
# the screen
Generator.mainloop()
Clear the label value on combo box selection.
You need to capture the ComboboxSelect event to do that and the function to execute if captured
the function should be like this
What you want to do here, is to capture the combobox event, and then, do the label configuration when capturing it,
Below is the code to do the thing. and you can add code there.
def comboboxEventCapture(e=None):
label.configure(text='')
# Your code after resetting variables!
Here's the event capturing part
combo.bind("<<ComboboxSelect>>", comboboxEventCapture)
You can name the function whatever you want though.
Note that the arguement e is needed because if the event is captured, the event itself is passed as a parameter into the function, that is of no use here (unless you are going to do something with it, then use e.objname)
The dynamic value should be displayed above clear button
The second label could be outside of get_log_file_name() function.
And also configure inside function. So you don't do duplicate Label widget, naming Label2
Also the pack() must be split to prevent an error.
To clear Label2 use .configure(text='')
We will be using ttk. So don't do this from tkinter import *
Code:
import tkinter as tk
from tkinter import ttk
from datetime import datetime
root = tk.Tk()
root.geometry("500x350")
root.resizable(False, False)
root.title('Test')
Generator = tk.Frame(root)
Generator.pack(padx=10, pady=10, fill='x', expand=True)
def clear():
label2.configure(text='')
def get_log_file_name(*arg):
date_Value = datetime.now().strftime("%Y_%m_%d_%I%M%S")
output_file_name_value = "Log_"+date_Value
if var.get() == "apple":
label2.configure(text="The value at index: "+output_file_name_value+".txt", font=('Helvetica 12'))
else:
label2.configure(text="The value at index: "+output_file_name_value+".html", font=('Helvetica 12'))
# Define Tuple of months
months = ('apple','banana')
# Create a Combobox widget
label2 = ttk.Label(Generator)
label2.pack()
label = ttk.Label(Generator, text="Selection_Option:",font=('Helvetica', 10, 'bold'))
label.pack(fill='x', expand=True)
var = tk.StringVar()
combo = ttk.Combobox(Generator, textvariable=var)
combo['values'] = months
combo['state'] = 'readonly'
combo.pack(padx=5, pady=5)
# Set the tracing for the given variable
var.trace('w', get_log_file_name)
# Create a button to clear the selected combobox
# text value
button = ttk.Button(Generator, text="Clear", command=clear)
button.pack(side='left')
# Make infinite loop for displaying app on
# the screen
Generator.mainloop()
Screenshot for apple:
Screenshot for banana:
Screenshot to clear Label2:

How to change values of combo after every new entry - Tkinter

I want to know how can I change values of combo box after every new entry in a Tkinter GUI?
SO below is the code where I am extracting values from a json file and showing it in a combo box. but I am also adding new values in the json file in the GUI but, I want to know how can I add new values to this combo box without opening the gui again in order to update the values. I want the values in combo to change immediately after a new entry is added into the json file.
coursefile = open('Course.json')
courserecord = json.load(coursefile)
coursenamerecord = []
for items in courserecord["COURSES"]:
coursenamerecord.append(items["Course Name"])
coursenamelabel = Label(tab5, text='Course Name:', font=('Open Sans Semibold', 12))
coursenamelabel.grid(row=1, column=0, padx=175, sticky='e')
coursenameentry = ttk.Combobox(tab5, width= 66, value=(coursenamerecord))
coursenameentry.place(x= 475, y= 183)coursefile = open('Course.json')
For that, you may use the combobox.config(). Get the users entry upon pressing a button, then append that value to a list and then reconfigure the value something like shown below
You may do something similar.
Here is an example
from tkinter import *
from tkinter import ttk
def update():
lst.append(entry.get())
combo.configure(values=lst)
lst = ['Math', 'Science', 'Language']
root = Tk()
var = StringVar()
entry = Entry(root)
entry.pack()
combo = ttk.Combobox(root, textvariable=var, values=lst)
combo.pack()
btn = Button(root, text='Update', command=update)
btn.pack()
root.mainloop()
So you have already stored the values in a list. Then get the value you need to store from the entry widget which you created in the last line(assuming the value u want to display inn combobox is getting from here). Append the list coursenamerecord with this value.
P.S.: Pls go through my profile to find a question "apply frame(in one file) to a root window(in another file)". I'd lov some explanatons there.

Radiobutton not updating values when clicked in python with tkinter

This is my first attempt at a GUI. Right now I just want to be able to click a radiobutton and make it print the value I assigned to the button. However, var.get() isn't giving me anything. I tried it with IntVar (and had my values as 1 and 2 instead of "proton" and "electron") and var.get() would just give me 0. With StringVar it gives nothing (nothing prints when choosecharge is called by the radiobutton). I've tried reading stuff about radiobuttons and I wrote my code based on how I saw it done and it successfully creates the radiobuttons, but the whole point is to be able to use their values when clicked.
import tkinter as tk
def choosecharge():
print(var.get())
root = tk.Tk()
var = tk.StringVar()
proton = tk.Radiobutton(root, text = "proton", variable = var, value = "proton", command = choosecharge)
proton.pack( )
electron = tk.Radiobutton(root, text="electron", variable = var, value= "electron", command = choosecharge)
electron.pack( )
root.mainloop()
I have taken a slightly different approach to accomplish this task.
I created a dictionary of the integer radiobutton values as key and
the string that you wish to print as value.
Used a label widget to print the string in the GUI
import tkinter as tk
root = tk.Tk()
# define an IntVar
var = tk.IntVar()
# create a dictionary of key:value pair as radiobutton_value: str_name_to_print
values = {1: "proton", 2: "electron"}
# instantiate a label widget
lbl = tk.Label(root)
def choosecharge():
# update the label widgets using the dictionary
lbl.config(text=values[var.get()])
proton = tk.Radiobutton(root, text="proton", variable=var, value=1, command=choosecharge)
proton.pack(anchor=tk.W)
electron = tk.Radiobutton(root, text="electron", variable=var, value=2, command=choosecharge)
electron.pack(anchor=tk.W)
# pack the label widget below the two radiobuttons
lbl.pack()
root.mainloop()
Screenshot
I have commented the lines in the code for better understanding. I hope this solution helps you.

error in using optionmenu widget in tkinter

I have written a code in python 2.7 which implements "optionmenu" widget. I am facing a problem that i have given six values in the tuple but when i select another option rather than "Gmail", i see only five values in the dropdown. can anyone tell me my mistake?
from Tkinter import *
import ttk
root = Tk()
choices = ("Gmail", "Outlook/Hotmail", "Yahoo", "Comcast", "AT&T", "Verizon")
dropdown_var = StringVar()
dropdown_var.set(choices[0]) # set default value
def data(*args):
value = dropdown_var.get()
print(value)
l = ttk.Label(root, text="Select your e-mail provider : ")
l.pack(side="left")
option = ttk.OptionMenu(root, dropdown_var, *choices)
option.pack(side="left", padx=10, pady=10)
b = ttk.Button(root, text="Click", command=data)
b.pack(side="bottom")
root.mainloop()
The issue you're facing is linked to the way you are defining the OptionMenu widget.
In fact, it's different from the tkinter OptionMenu because you set the default value inside the declaration. So when you unpack the values, the first index "Gmail" is taken as the default parameter for the widget, and the others are the options values.
(In addition, you don't need to set dropdown_var before)
Try this version :
choices = ("Gmail", "Outlook/Hotmail", "Yahoo", "Comcast", "AT&T", "Verizon")
dropdown_var = StringVar()
def data(*args):
value = dropdown_var.get()
print value # no bracket for python2
l = ttk.Label(root, text="Select your e-mail provider : ")
l.pack(side="left")
# the 3rd parameter is the default value
option = ttk.OptionMenu(root, dropdown_var, choices[0], *choices)
option.pack(side="left", padx=10, pady=10)

How to control the tkinter combobox selection highlighting

I wrote a small farad converter to learn GUI programming. It works great, looks fine-ish. The only problem is I can't seem to figure out how to control this strange highlighting that comes up on my ttk.Combobox selections. I did use a ttk.Style(), but it only changed the colors of the ttk.Combobox background, entries, etc. I also tried changing openbox/gtk themes.
I'm talking about what's seen there on the text "microfarads (uF)".
It'd be fine, if it highlighted the entire box; but I'd rather have it gone completely.
How can I manipulate a ttk.Combobox's selection highlight?
# what the farad?
# thomas kirkpatrick (jtkiv)
from tkinter import *
from tkinter import ttk
# ze la programma.
def conversion(*args):
# this is the numerical value
inV = float(inValue.get())
# these two are the unit (farads, microfarads, etc.) values
inU = inUnitsValue.current()
outU = outUnitsValue.current()
# "mltplr" is multiplied times inValue (inV)
if inU == outU:
mltplr = 1
else:
mltplr = 10**((outU - inU)*3)
outValue.set(inV*mltplr)
# start of GUI code
root = Tk()
root.title("What the Farad?")
# frame
mainFrame = ttk.Frame(root, width="364", padding="4 4 8 8")
mainFrame.grid(column=0, row=0)
# input entry
inValue = StringVar()
inValueEntry = ttk.Entry(mainFrame, width="20", justify="right", textvariable=inValue)
inValueEntry.grid(column=1, row=1, sticky="W")
# input unit combobox
inUnitsValue = ttk.Combobox(mainFrame)
inUnitsValue['values'] = ('kilofarads (kF)', 'farads (F)', 'millifarads (mF)', 'microfarads (uF)', 'nanofarads (nF)', 'picofarads (pF)')
inUnitsValue.grid(column=2, row=1, sticky="e")
inUnitsValue.state(['readonly'])
inUnitsValue.bind('<<ComboboxSelected>>', conversion)
# result label
outValue = StringVar()
resultLabel = ttk.Label(mainFrame, textvariable=outValue)
resultLabel.grid(column=1, row=2, sticky="e")
# output unit combobox
outUnitsValue = ttk.Combobox(mainFrame)
outUnitsValue['values'] = ('kilofarads (kF)', 'farads (F)', 'millifarads (mF)', 'microfarads (uF)', 'nanofarads (nF)', 'picofarads (pF)')
outUnitsValue.grid(column=2, row=2, sticky="e")
outUnitsValue.state(['readonly'])
outUnitsValue.bind('<<ComboboxSelected>>', conversion)
# padding for widgets
for child in mainFrame.winfo_children(): child.grid_configure(padx=4, pady=4)
# focus
inValueEntry.focus()
# bind keys to convert (auto-update, no button)
root.bind('<KeyRelease>', conversion)
root.mainloop()
Could it be that with a readonly combobox the problem is not the selection but the relatively strong focus-indicator?
With this workarround you lose the ability to control your program by keyboard. To do it right you would have to change the style of the focus-highlighting.
from tkinter import *
from ttk import *
def defocus(event):
event.widget.master.focus_set()
root = Tk()
comboBox = Combobox(root, state="readonly", values=("a", "b", "c"))
comboBox.grid()
comboBox.set("a")
comboBox.bind("<FocusIn>", defocus)
mainloop()
You can use the Combobox's selection_clear() method to clear the selection whenever you want.
e.g
inUnitsValue.selection_clear()
Just refresh the selected value of the Combobox.
This will help for removing the highlight.
import tkinter.ttk
import tkinter
items = ["test1","test2","test3","test4"]
class TkCombobox(tkinter.ttk.Combobox):
def __init__(self, *arg, **kwarg):
super(TkCombobox, self).__init__(*arg, **kwarg)
self._strvar_ = tkinter.StringVar()
self._strvar_.set("")
self["textvariable"] = self._strvar_
self.bind("<<ComboboxSelected>>", self.highlight_clear)
def highlight_clear(self, event):
current = self._strvar_.get()
self.set("")
self.set(current)
master = tkinter.Tk();master.geometry("400x400")
c = TkCombobox(master, values=items, state="readonly")
c.pack()
master.mainloop()

Categories