reverse button to switch optionmenu values in tkinter - python

I am creating a currency converter that asks the user to choose the starting and ending currencies with two optionmenu widgets. The problem I have run into is after the currency has been converted, I want to create a button that reverses the optionmenu values to convert back to the original currency. For example, I originally convert 20 USD to EUR. I want the button to reverse it to convert 20 EUR to USD and reflect the change in the optionmenus. Here is the code I have:
currency_list = []
infile = open('currency_list.txt', 'r')
for currency in infile:
currency_list[:-1]
currency_list.append(currency.strip("\t\n\t"))
initial1 = currency_list[-16] # initially set first option menu to USD from currency list
initial2 = currency_list[43] # initially set second option menu to EUR from currency list
my_list = [currency_list[-16], currency_list[43]]
class CurrencyConverter(tk.Frame):
def reverse(self):
my_list.reverse()
print (my_list)
self.currency_1_menu = tk.OptionMenu(self, self.currency_1, *currency_list)
self.currency_2_menu = tk.OptionMenu(self, self.currency_2, *currency_list)
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
body_color = "white"
body_font_color = "black"
entry_color = body_color
entry_font_color = "gray26"
self.currency_1 = tk.StringVar() # currency to convert from
self.currency_2 = tk.StringVar() # currency to convert to
self.currency_1.set(my_list[0]) # set value from list above
self.currency_2.set(my_list[1]) # set value from list above
self.answer = tk.StringVar() # result from conversion
self.value_id = tk.StringVar() # number user types in to convert from
self.header_text = tk.StringVar() # header to display information
logo = tkinter.PhotoImage(file = "logo_copy.gif") # import logo. Not working!!
label = tk.Label(self,image = logo)
label.config(bg = body_color)
label.grid(row = 0, column = 2, rowspan = 2)
self.header = tk.Label(self, textvariable = self.header_text)
self.result_label = tk.Label(self, textvariable = self.answer, fg = body_font_color)
self.value_entry = tk.Entry(self, textvariable = self.value_id)
self.currency_1_menu = tk.OptionMenu(self, self.currency_1, *currency_list)
self.currency_2_menu = tk.OptionMenu(self, self.currency_2, *currency_list)
self.calculate_button = tk.Button(self, command = self.convert, text = 'calculate')
self.reverse_button = tk.Button(self, command = lambda: self.reverse, text = 'reverse')
home_page_button = tk.Button(self, text = "Home Page", command = lambda: controller.show_frame(StartPage))
self.header.config(bg = body_color, font = ('arial', 12), fg = entry_font_color)
self.result_label.config(font = ('Arial', 36))
self.value_entry.config(font = 'bold', justify = 'center', bg = entry_color, fg = entry_font_color, highlightthickness = 0)
self.currency_1_menu.config(bg = body_color, width = 25, height = 2)
self.currency_2_menu.config (bg = body_color, width = 25, height = 2)
self.result_label.config (bg = body_color)
self.calculate_button.config (bg = body_color, highlightbackground = body_color)
self.reverse_button.config (bg = body_color, highlightbackground = body_color)
self.header.grid(row = 0, column = 0, sticky = 'w')
self.result_label.grid(row = 1, column = 0, sticky = 'w')
self.value_entry.grid(row = 2, column = 0)
self.currency_1_menu.grid (row = 2, column = 1)
self.currency_2_menu.grid (row = 3, column = 1)
self.calculate_button.grid(row = 4, column = 0)
self.reverse_button.grid(row = 2, column = 2, rowspan = 2)
home_page_button.grid(row = 4, column = 1)
def convert(self):
self.currency_1_iso = self.currency_1.get()[0:3]
self.currency_2_iso = self.currency_2.get()[0:3]
url = "https://www.xe.com/currencyconverter/convert/?Amount=" + self.value_id.get() + "&From=" + self.currency_1_iso + "&To=" + self.currency_2_iso
print(url)
if (not os.environ.get('PYTHONHTTPSVERIFY', '') and
getattr(ssl, '_create_unverified_context', None)):
ssl._create_default_https_context = ssl._create_unverified_context
html_code = urllib.request.urlopen(url).read()
self.soup = BeautifulSoup(html_code, 'html.parser')
self.result = self.soup.find('span', {'class': "uccResultAmount"}).string
self.answer.set(self.result + " " + self.currency_2_iso)
self.header_text.set(self.value_id.get() + self.currency_1.get()[5:] + ' equals')

Your current attempt at reverse() creates brand new OptionMenus - and never actually displays them. You don't actually need to touch the OptionMenus themselves, just swap the values in the two variables they are tied to:
temp = self.currency_1.get()
self.currency_1.set(self.currency_2.get())
self.currency_2.set(temp)

Related

Is there a way to make the scrollbar longer in tkinter?

I have a tkinter listbox inside a frame which is inside a canvas. The scrollbar works very well through this code:
messagesList.config(yscrollcommand = scrollbar.set)
scrollbar.config(command=messagesList.yview)
However, I wanted the scrollbar to be longer so that I can actually scroll. I tried things such as making the frame bigger or make it take more space with padx and pady. Is there any way to make the scrollbar longer?
The image of how it currently is:
Complete code:
import tkinter as tk
from tkinter import ttk
import tkinter.font as tkFont
root = tk.Tk()
root.title("Messager")
root.geometry("1300x700")
root.resizable(height = 0, width = 0)
#makes window not resizable
class Elements:
def __init__(self, main):
def sendMessage():
user = userName.get()
message = userMessage.get()
print(user+ " username")
print(message + " message")
theCan = tk.Canvas(main)
titleFrame = tk.LabelFrame(main)
mainFrame = tk.LabelFrame(theCan)
greeting = tk.Label(titleFrame, text="Messager", bg = "#74a5f2", font = (None, 35))
userName = tk.Entry(titleFrame, font = (None, 15))
userName.insert(0, "An Unnamed Scrub")
userMessage = tk.Entry(titleFrame, font = (None, 15))
userMessage.insert(0,"Your Message")
sendButton = tk.Button(titleFrame, command = sendMessage, text = "Send!", bg = "#74a5f2", font = (None, 22))
titleMessage = tk.Label(mainFrame, text = "MESSAGER", bg = "#74a5f2", font = (None, 50))
messagesList = tk.Listbox(mainFrame)
scrollbar = tk.Scrollbar(mainFrame, orient=tk.VERTICAL, relief = 'flat')
messagesList.config(yscrollcommand = scrollbar.set)
scrollbar.config(command=messagesList.yview)
testList = ["apple", "orange","apple", "orange","apple", "orange","apple", "orange","apple", "orange","apple", "orange","apple", "orange"]
for item in testList:
messagesList.insert(tk.END, item)
placeholder = tk.Label(main, text = " ")
placeholder1 = tk.Label(main, text = " ")
placeholder2 = tk.Label(main, text = " ")
placeholder3 = tk.Label(main, text = " ")
placeholder4 = tk.Label(main, text = " ")
placeholder5 = tk.Label(main, text = " ")
placeholder6 = tk.Label(main, text = " ")
placeholder7 = tk.Label(main, text = " ")
placeholder8 = tk.Label(main, text = " ")
placeholder9 = tk.Label(main, text = " ")
placeholder10 = tk.Label(main, text = " ")
placeholder11 = tk.Label(main, text = " ")
placeholder12 = tk.Label(main, text = " ")
placeholder13 = tk.Label(main, text = " ")
placeholder.grid(row = 1, column = 1)
placeholder1.grid(row = 2, column = 2)
placeholder2.grid(row = 3, column = 3)
placeholder3.grid(row = 4, column = 4)
placeholder4.grid(row = 5, column = 5)
placeholder5.grid(row = 6, column = 6)
placeholder6.grid(row = 7, column = 7)
placeholder7.grid(row = 8, column = 8)
placeholder8.grid(row = 1, column = 9)
placeholder9.grid(row = 1, column = 10)
placeholder10.grid(row = 1, column = 11)
placeholder11.grid(row = 1, column = 12)
placeholder12.grid(row = 1, column = 13)
placeholder13.grid(row = 1, column = 14)
#placeholders to move the mainframe frame to the center
titleFrame.grid(row = 1, padx = 20, pady = 20)
greeting.grid(pady = 20)
userName.grid()
userMessage.grid(pady = 20)
sendButton.grid()
mainFrame.grid()
titleMessage.grid(pady = 20)
messagesList.grid()
theCan.grid(row = 1, column = 15, pady = 20)
scrollbar.grid(sticky = "ne", rowspan = 5)
postEverything = Elements(root)
root.mainloop()
As has been said already, you need to place the box and the scroll bar on the same row using grid
messagesList = tk.Listbox(mainFrame)
scrollbar = tk.Scrollbar(mainFrame, orient=tk.VERTICAL, relief = 'flat')
messagesList.config(yscrollcommand = scrollbar.set)
scrollbar.config(command=messagesList.yview)
messagesList.grid(row=0,column=0)
scrollbar.grid(row=0,column=1,sticky = "ns")
Also note that I've changed the sticky attribute to be "ns" which means the scroll bar will stretch to fit the row and match the height of the messagesList widget.

Description photo viewer in GUI - Python

I'm new in Python, I am searching for solution with this error. I got stuck with this assignment.
I'm trying to change the description by each picture but unfortunately I failed.
from tkinter import *
from PIL import Image, ImageTk
root = Tk()
root.title("Image Viewer")
root.config(bg = "Grey")
frame1 = Frame(root, width = 500, height = 325, bg = "Silver")
frame1.pack(side = TOP)
frame2 = Frame(root, width = 500, height = 25, borderwidth= 1, bg = "Grey")
frame2.pack(side = BOTTOM, pady= 2)
# Image:
img1 = ImageTk.PhotoImage(Image.open("dec19.jpg"))
img2 = ImageTk.PhotoImage(Image.open("dec20.jpg"))
img3 = ImageTk.PhotoImage(Image.open("dec21.jpg"))
# Description:
des1= Label(frame1, text = "I am happy this day")
des2= Label(frame1, text = "going somewhere")
des3= Label(frame1, text = "Today is a great day")
# , width = 500, height = 315
num = 1
# List:
img_list = [img1, img2,img3]
des_list = [1 , 2, 3]
# Startup:
my_label = Label(frame1,image = img1)
my_label.pack()
my_des = Label(frame1, text = f"Description{num}")
my_des.pack(side = BOTTOM)
# Definning Command functions:
def close_app():
exit()
def forward(image_num):
global my_label
global prev
global next1
global num
global my_des
global des_list
my_label.pack_forget()
# .grid_forget()
my_label = Label(frame1, image= img_list[image_num-1])
my_label.pack()
my_des.pack_forget()
my_des = Label(frame1, text = f"Description{des_list[image_num-1]}")
my_des.pack()
# .grid(row = 0, column = 0, columnspan = 3)
next1 = Button(frame2, text = "Next", command = lambda: forward(image_num+1))
next1.grid(row = 1, column = 2)
prev = Button(frame2, text = "Previous", command = lambda : back(image_num-1))
prev.grid(row = 1, column = 0)
if image_num == 3:
next1 = Button(frame2, text = "Next", state = DISABLED)
next1.grid(row = 1, column = 2)
prev = Button(frame2, text = "Previous", state = DISABLED, command =lambda : back(2))
prev.grid(row = 1, column = 0)
exits = Button(frame2, text = "Exit", command = close_app)
exits.grid(row = 1, column = 1)
next1 = Button(frame2, text = "Next", command = lambda: forward(2))
next1.grid(row = 1, column = 2)
root.mainloop()
If you want that each description is different you can create a dictionary wher you bind each image index to its description
image_description = {
1 : 'I am happy this day',
2 : "going somewhere",
3: "Today is a great day"
}
Now that you have this dictionary when you call the function that changes the image instead having a static string that changes only the number ( f"Description{des_list[image_num-1]}" ) you can get the datas from the dictionary
so change this 3 lines
my_des.pack_forget()
my_des = Label(frame1, text = f"Description{des_list[image_num-1]}")
my_des.pack()
to this
my_des.configure(text = f"{image_description[image_num]}")

Is it possible to grab a label variable and put into list with tkinter

I've created a temperature converter programme in which the calculated temperature from an entry widget gets displayed in a separate label, what I need to do is to grab that converted variable and put it into a list.
I think that making a connected entry widget to the label widget would work where they are connected so I could grab the variable using the .get method but that would look awfully messy. Is there any other way I could proceed with this?
This is my first post and I am a beginner in Python, very sorry if the code looks messy and if I included too much code.
data = []
tempVal = "Celcius"
def store_temp(sel_temp):
global tempVal
tempVal = sel_temp
class Calculator:
def __init__(self, num_a, num_b):
self.num_a= num_a
self.num_b = num_b
def convert(self):
if tempVal == 'Fahrenheit':
return float((float(self.num_a) - 32)* 5 / 9)
if tempVal == 'Celcius':
return float((float(self.num_a) * 9/ 5) + 32)
def display_add(entry_numa,entry_numb,label_answer):
#get the value from entry_numa
num_a = entry_numa.get()
num_b = entry_numb.get()
num_a = str(num_a)
num_b = str(num_b)
#create an object
global data
calc = Calculator(num_a,num_b)
label_answer['text'] = calc.convert()
data += [calc]
def calc_history():
global data
#creat e another window
window_calc_list = Tk()
window_calc_list.geometry("400x200")
#create a listbox
listbox_calc_list = Listbox(window_calc_list, width= 300)
listbox_calc_list.pack()
listbox_calc_list.insert(END, "list of data")
for info in data:
listbox_calc_list.insert(END, str(info.num_a) + " " + str(info.num_b) + " " )
window_calc_list.mainloop()
def main():
window = Tk()
window.geometry("500x150")
validate_letter = window.register(only_letters)
validate_nb = window.register(only_numbers_max_3)
label = Label(window, width = 30, background = 'lightblue', text='enter temperature, only numbers')
label.grid(row=0, column=0)
entry_numa = Entry(window, width = 30, validate="key", validatecommand=(validate_nb, '%d', '%P'))
entry_numa.grid(row = 0, column = 1)
#create another label and entry object for num_b
label_numb = Label(window, width = 30, background = 'lightblue', text='enter location, only letters')
label_numb.grid(row=1, column=0)
entry_numb = Entry(window, width = 30, validate="key", validatecommand=(validate_letter, '%d', '%S'))
entry_numb.grid(row = 1, column = 1)
#create another label to display answer
label_answer = Label(window, width = 30, background = 'lightyellow')
label_answer.grid(row = 2, column = 1)
entry_answer = Entry(window, width = 30)
entry_answer.grid(row = 2, column = 0)
button_add = Button(window, text = "ADD", command = lambda: display_add(entry_numa,entry_numb,label_answer))
button_add.grid(row=3, column = 0)
button_delete = Button(window, text = "DELETE", command = lambda: delete_data(data))
button_delete.grid(row=3, column = 2)
#create another button to display all previous calculations
button_display = Button(window,text = "calc_history", command = lambda: calc_history())
button_display.grid(row=3, column = 1)
var = StringVar()
dropDownList = ["Celcius", "Fahrenheit"]
dropdown = OptionMenu(window, var,dropDownList[0], *dropDownList, command=store_temp)
dropdown.grid(row=0, column=2)
window.mainloop()
A tk.Label displayed value can be accessed via the text property
, labelwidgetname['text'].
Depeneding on when and how you want the independent list of stored values
to be updated there are a variety of options. The example shows one if the
user is required to press a submission button. This could be adapted,
for example,when the tempreture calculation is performed.
Of course it would be simpler to update the list of stored values directly at the point in the script where the calculated tempreture for the label text has been derived.
import tkinter as tk
stored_values = []
def add_labelvalue_tolist(temp):
'''Store label value to list.'''
stored_values.append(temp)
print('contents of list', stored_values)
def add_entry_tolabel(event):
display_label['text'] = user_entry.get()
ROOT = tk.Tk()
user_entry = tk.Entry()
user_entry.grid(column=0, row=0)
user_entry.bind('<KeyRelease>', add_entry_tolabel)
display_label = tk.Label()
display_label.grid(column=1, row=0)
# update list via button command linked to label text value
add_button = \
tk.Button(text='add to list',
command=lambda:add_labelvalue_tolist(display_label['text']))
add_button.grid(column=0, row=1)
ROOT.mainloop()
try making a function that is like this
def letterused():
converter=(letter.get())# letter is a entry box at the bottom is the code
converted.set(converter)
for i in range(1):
used_letters1.append(converter) #list
letter = ttk.Entry(root, width = 20,textvariable = letter)
letter.pack()

Radio Buttons tkinter python

I have an issue where all my radio buttons are selected when I try to click one of them. It is for a conversion calculator, so once I solve this issue I will be able to carry the same code over for my other conversions. Any help is greatly appreciated.
Thanks,
Jamie
`from tkinter import*
from tkinter import ttk
class GUI:
def __init__(self, root):
notebook = ttk.Notebook(root)
notebook.pack()
self.temp_frame = ttk.Frame(notebook)
self.length_frame = ttk.Frame(notebook)
self.weight_frame = ttk.Frame(notebook)
#-----------------Length------------------------#
notebook.add(self.length_frame, text = "Length")
#Radio Buttons
v = StringVar()
MODES = ["mm","cm","Inch","Feet","Yards","Metre","Km","Miles"]
v.set("0") # initialize
r=0
for r in range(len(MODES)):
b = ttk.Radiobutton(self.length_frame, text=MODES[r], variable=v )
b.grid(row=r ,column = 0, sticky = W)
#Radio Buttons
v1 = StringVar()
MODES1 = ["mm","cm","Inch","Feet","Yards","Metre","Km","Miles"]
v1.set("0")#initialize
r=0
for r in range(len(MODES1)):
b = ttk.Radiobutton(self.length_frame, text=MODES1[r], variable=v1 )
b.grid(row=r ,column = 6, sticky = W)
#Entry Box
self.Text_length_left = StringVar()
self.entry_length_left = ttk.Entry(self.length_frame, textvariable = self.Text_length_left, width = 15)
self.entry_length_left.grid(row = 4, column = 2)
self.Text_length_right = StringVar()
self.entry_length_right = ttk.Entry(self.length_frame, textvariable = self.Text_length_right, width = 15, state = "readonly")
self.entry_length_right.grid(row = 4, column = 4)
#Label
self.label_3 = Label(self.length_frame, text = "From:")
self.label_3.grid(row = 3, column = 2)
self.label_4 = Label(self.length_frame, text = "To:")
self.label_4.grid(row = 3, column = 4)
self.label_1 = Label(self.length_frame, text = "-->")
self.label_1.grid(row = 4, column = 3)
self.label_2 = Label(self.length_frame, text = " ")
self.label_2.grid(row = 4, column = 5)
#---------------------Temp Frame ----------------------#
notebook.add(self.temp_frame, text = "Temperature")
if __name__ == "__main__":
root = Tk()
app = GUI(root)
root.mainloop()`
You never set the value keyword. This is what's stored in the control variable for a group of radiobuttons when clicked.

TKinter math output to canvas.create_text

I am trying to calculate a formula and display its output as a table in TKinter. Since it is not working, I am just trying to get a simple result and print it to a canvas widget. When this gets working I will do the entire loan formula. As it is I get no output in the GUI or in the console.
Is this even possible to place the result of a calculation as text in canvas.create_text?
from tkinter import * # Import tkinter
width = 500
height = 500
class MainGUI:
def __init__(self):
window = Tk() # Create a window
window.title(" Loan Schedule ") # Set title
frame1 = Frame(window)
frame1.grid(row = 1, column = 1)
Label(frame1, text = " Loan Amount ").grid(row = 1, column = 1, sticky = W)
self.v1 = StringVar()
Entry(frame1, textvariable = self.v1, justify = RIGHT).grid(row = 1, column = 2)
Label(frame1, text = " Years ").grid(row = 1, column = 3, sticky = W)
self.v2 = StringVar()
Entry(frame1, textvariable = self.v2, justify = RIGHT).grid(row = 1, column = 4)
btCalculate = Button(frame1, text = " Calculate ", command = self.calculate()).grid(row = 1, column = 5, sticky = E)
frame2 = Frame(window)
frame2.grid(row = 2, column = 1)
self.canvas = Canvas(frame2, width = width, height = height, bg = "white")
self.canvas.pack()
self.canvas.create_text(25, 25, text = self.calculate(), tags = "text")
window.mainloop() # Create an event loop
def calculate(self):
result = self.v1.get() + self.v2.get()
print(result)
return result
MainGUI()
command require function name without ()
command = self.calculate
so now it works
from tkinter import * # Import tkinter
width = 500
height = 500
class MainGUI:
def __init__(self):
window = Tk() # Create a window
window.title(" Loan Schedule ") # Set title
frame1 = Frame(window)
frame1.grid(row = 1, column = 1)
Label(frame1, text = " Loan Amount ").grid(row = 1, column = 1, sticky = W)
self.v1 = StringVar()
Entry(frame1, textvariable = self.v1, justify = RIGHT).grid(row = 1, column = 2)
Label(frame1, text = " Years ").grid(row = 1, column = 3, sticky = W)
self.v2 = StringVar()
Entry(frame1, textvariable = self.v2, justify = RIGHT).grid(row = 1, column = 4)
btCalculate = Button(frame1, text = " Calculate ", command = self.calculate).grid(row = 1, column = 5, sticky = E)
frame2 = Frame(window)
frame2.grid(row = 2, column = 1)
self.canvas = Canvas(frame2, width = width, height = height, bg = "white")
self.canvas.pack()
self.canvas.create_text(55, 10, text = self.add_text(), tags = "text")
window.mainloop() # Create an event loop
def calculate(self):
result = int(self.v1.get()) + int(self.v2.get())
self.canvas.create_text(25, 25, text = result, tags = "text")
print(result)
return result
def add_text(self):
return "HELLO WORLD"
MainGUI()
by the way: line below means - run self.calculate() and result assign to command
command = self.calculate()

Categories

Resources