Description photo viewer in GUI - Python - 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]}")

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.

why is the layout all messed up if i expand the window, python tkinter

i want it to expand the size accordingly if the window is expanded, so far i use the grid.row/column configure to make its weight =1 but it will be all messed up it i expand the window.
import time
import tkinter as tk
#Initialise the window
clock = tk.Tk()
clock.title('Easy CLock')
clock.configure(bg='#121212')
clock.columnconfigure(0, weight = 1)
clock.rowconfigure(0, weight = 1)
border_effects = {
"flat": tk.FLAT,
"sunken": tk.SUNKEN,
"raised": tk.RAISED,
"groove": tk.GROOVE,
"ridge": tk.RIDGE,
}
#Logo will be under the main parent
logo = tk.PhotoImage(file = r'C:\Users\User\VSC\Alarm\Logo1.png')
logo_size = logo.subsample(5)
#Time and Date function
def time_date():
# current time
current_time = time.strftime('%H:%M:%S')
current_date = time.strftime(r'%m/%d/%Y')
clock.after(200, time_date)
#Displays the time
c_time = tk.Label(f_time, text = current_time, fg='white', bg='#121212', font=('Verdana', 30))
c_date = tk.Label(f_time, text = current_date, font=('Verdana', 10), fg='white', bg='#121212')
c_time.grid(column=0, row=0)
c_date.grid(column=0, row=1)
#alarm button command
def alarm_func():
#Alarm label
c_clicked = tk.Label(f_alarm, text='Alarm Interface', fg='white', bg='#121212')
c_clicked.grid(column=0, row=1, sticky = 'N')
def recall_frame(event):
if event == f_alarm:
event.grid_forget()
f_time.grid(column=0, row =1, columnspan = 4, sticky = 'N')
elif event == f_time:
event.grid_forget()
f_alarm.grid(column=0, row=1, columnspan = 4, rowspan = 2)
def back_func():
pass
#Creating Frames
f_time = tk.Frame(clock) #Clock Button
f_alarm = tk.Frame(clock) #Alarm Buttton
#configure the frames
f_time.configure(bg = '#121212')
f_alarm.configure(bg = '#121212')
#Setting label in the frame
f_lbl = tk.Label(clock, text= ' Simplistic Clock', image = logo_size, font=('Verdana', 30), fg='white', bg='#121212', compound = tk.LEFT)
time_but = tk.Button(clock, text='Clock', command= lambda :[time_date(), recall_frame(f_alarm)], bg='#f39c12', width = 15, relief = border_effects['ridge'])
alarm_but = tk.Button(clock, text = 'Alarm', command = lambda :[alarm_func(), recall_frame(f_time)], bg='#f39c12', width = 15, relief = border_effects['ridge'])
quit_but = tk.Button(clock, text='Exit', command = clock.quit, bg='#f39c12', width = 15, relief = border_effects['ridge'])
back_but = tk.Button(clock, text = 'Back To Home', command = back_func, bg='#f39c12', width = 15, relief = border_effects['ridge'])
f_lbl.config(borderwidth = 4, relief = border_effects['sunken'])
f_lbl.grid_columnconfigure(0, weight = 1)
#Putting it on the frames
f_lbl.grid(column = 0, row = 0, columnspan = 4, sticky = 'N')
time_but.grid(column = 0, row = 3)
alarm_but.grid(column = 1, row = 3)
back_but.grid(column = 2, row = 3)
quit_but.grid(column = 3, row = 3)
clock.mainloop()
also, why does the border in the f_lbl, simplistic clock not fully extended through out all 4 column since i put columnspan = 4 , and weight = 1 , should't it expand fully through all 4 columns?

reverse button to switch optionmenu values in tkinter

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)

How do you say "If button is pressed, then do this" in python tkinter?

I am trying to say "if the thing that you are trying to press equal for is an integer, then do what i have, but if it is a string, then print either "cos(whatever number)", "tan(whatever number)", or "sin(whatever number)". Please help clarify how to do this. Thank you.
from tkinter import*
root = Tk()
def btnPress(num):
global result
result = result+str(num)
equation.set(result)
def equalPress():
global result
total = str(eval(result))
equation.set(total)
result = total
def clear():
global result
result = ""
equation.set("")
result = ""
btnWidth = 5
equation = StringVar()
equation.set("Enter your equation.")
calculation = Label(root, textvariable = equation, width = btnWidth*4)
calculation.grid(row = 0, column = 0, columnspan = 4)
Button0 = Button(root, text = "0", command=lambda:btnPress(0), width = btnWidth)
Button0.grid(row = 4, column = 2)
Button1 = Button(root, text = "1", command=lambda:btnPress(1), width = btnWidth)
Button1.grid(row = 1, column = 1)
Button2 = Button(root, text = "2", command=lambda:btnPress(2), width = btnWidth)
Button2.grid(row = 1, column = 2)
Button3 = Button(root, text = "3", command=lambda:btnPress(3), width = btnWidth)
Button3.grid(row = 1, column = 3)
Button4 = Button(root, text = "4", command=lambda:btnPress(4), width = btnWidth)
Button4.grid(row = 2, column = 1)
Button5 = Button(root, text = "5", command=lambda:btnPress(5), width = btnWidth)
Button5.grid(row = 2, column = 2)
Button6 = Button(root, text = "6", command=lambda:btnPress(6), width = btnWidth)
Button6.grid(row = 2, column = 3)
Button7 = Button(root, text = "7", command=lambda:btnPress(7), width = btnWidth)
Button7.grid(row = 3, column = 1)
Button8 = Button(root, text = "8", command=lambda:btnPress(8), width = btnWidth)
Button8.grid(row = 3, column = 2)
Button9 = Button(root, text = "9", command=lambda:btnPress(9), width = btnWidth)
Button9.grid(row = 3, column = 3)
Button10 = Button(root, text = "tan", command=lambda:btnPress("tan "), width = btnWidth)
Button10.grid(row = 3, column = 0)
Button11 = Button(root, text = "sin", command=lambda:btnPress("sin "), width = btnWidth)
Button11.grid(row = 2, column = 0)
Button12 = Button(root, text = "cos", command=lambda:btnPress("cos "), width = btnWidth)
Button12.grid(row = 1, column = 0)
plus = Button(root, text = "+", command = lambda:btnPress("+"), width = btnWidth)
plus.grid(row = 1, column = 4)
plus = Button(root, text = "-", command = lambda:btnPress("-"), width = btnWidth)
plus.grid(row = 2, column = 4)
plus = Button(root, text = "*", command = lambda:btnPress("*"), width = btnWidth)
plus.grid(row = 3, column = 4)
plus = Button(root, text = "/", command = lambda:btnPress("/"), width = btnWidth)
plus.grid(row = 4, column = 4)
plus = Button(root, text = ".", command = lambda:btnPress("."), width = btnWidth)
plus.grid(row = 4, column = 1)
if ==
equal = Button(root, text = "=", command = equalPress, width = btnWidth)
equal.grid(row = 4, column = 3)
equal = Button(root, text = "C", command = clear, width = btnWidth)
equal.grid(row = 4, column = 0)
root.mainloop()
Simply check for the contents of num:
def btnPress(num):
global result
if num == "tan ":
result = tan(float(result))
elif num == "cos ":
result = tan(float(result))
...
else:
result = result+str(num)

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