python tkinter button command does not work - python

I'm trying to create a program in python tkinter which user first have to login, then the first page is closed and new one opens with some buttons inside.
button must change it's color and text on click but it does not do anything
from tkinter import *
def button_clicked(button):
Button(button).configure(bg="red", text="not Active")
def open_setting_page():
loginPage.destroy()
setting_page = Tk()
setting_page.title("Setting")
setting_page.geometry("400x300")
b2 = Button(setting_page, text="Active", height=5, width=10, bg="green",command=lambda:button_clicked(b2)).grid(row=0, column=0)
b3 = Button(setting_page, text="Active", height=5, width=10, bg="green",command=lambda:button_clicked(b3)).grid(row=0, column=1)
setting_page.mainloop()
#program starts here
loginPage = Tk()
loginPage.title("Security System")
loginPage.geometry("400x300")
Label(text="\n\n\n\n").pack()
l1 = Label(text="Enter Password:")
l1.pack()
password_entry = Entry()
password_entry.insert(0, "Enter Your Password...")
password_entry.pack()
b1 = Button(text="Login", command=open_setting_page)
b1.pack()
loginPage.mainloop()
I want the buttons color and text be changed on click but noting happens when I click it.

there are two problems in this code:
in open_setting_page() -> the variables b2 and b3 become None because Button(XXX).grid() returns None -> lets separate the button creation and the grid placement into 2 steps.
in button_clicked(button) function -> Button(button).configure is wrong. it should be button.configure(XX) to get hold of the button that you gave to the function.
Here is how these two functions could look like:
def button_clicked(button):
button.configure(bg="red", text="not Active")
def open_setting_page():
loginPage.destroy()
setting_page = Tk()
setting_page.title("Setting")
setting_page.geometry("400x300")
b2 = Button(setting_page, text="Active", height=5, width=10, bg="green", command=lambda: button_clicked(b2))
b3 = Button(setting_page, text="Active", height=5, width=10, bg="green", command=lambda: button_clicked(b3))
b2.grid(row=0, column=0)
b3.grid(row=0, column=1)
setting_page.mainloop()

Related

Python lists not updating with .append()

I am trying to make a program that stores drinks and displays them when a user wants to (when they click b5), but the .append() function isn’t working. I think it’s because the list is not saving after the user inputs a drink. My guess is that I might need a while loop somewhere, but I am not sure where to put it. I also wonder if there isn’t a better way of storing and retrieving these. Here is a shortened version of the code.
Here are the relevant functions.
def save_d(added_drink_ent, top):
global drinks_list
drinks_list = []
newtop = Toplevel(root)
newtop.geometry("200x200")
newtop.title("Drink Added")
label = Label(newtop, text=f"Added {added_drink_ent.get()}")
label.pack()
close_btn = Button(newtop, text='Close', command=lambda t=top, n=newtop: close(t,n))
close_btn.pack()
drinks_list.append(added_drink_ent.get())
def add_drink():
top = Toplevel(root)
top.title("Add Drink")
top.geometry('400x100')
label = Label(top, text="Add a new drink to the list.")
label.pack()
entry_drink_ent = Entry(top)
entry_drink_string = str(entry_drink_ent)
entry_drink_ent.pack()
b1 = Button(top, text='Submit Add Drink', command=lambda: save_d(entry_drink_ent, top))
b1.pack()
b2 = Button(top, text="Close", command=top.destroy)
b2.pack()
def close(top, newtop):
top.destroy()
newtop.destroy()
def display():
newtop2 = Toplevel(root)
label3 = Label(newtop2, font=("Arial", 20))
label3.config(text=f"These are the drinks you had today: {drinks_list}")
label3.pack()
The buttons. b5 is the one that should display the list.
b1 = Button(root, text="START TIMER", width=25, borderwidth=5, command=start, font=('Arial', 30))
b1.pack()
b2 = Button(root, text="STOP TIMER", width=25, borderwidth=5, command=stop, font=('Arial', 30))
b2.pack()
b3 = Button(root, text="RESET BUTTON", width=25, borderwidth=5, command=reset, font=('Arial', 30))
b3.pack()
b4 = Button(root, text="ADD DRINK", width=25, borderwidth=5, command=add_drink, font=('Arial', 30))
b4.pack()
b5 = Button(root, text="DISPLAY DRINK LOG", width=26, borderwidth=5, command=display, font=('Arial', 30))
b5.pack()
Are you clearing drink_lists in save_d every time?
def save_d(added_drink_ent, top):
global drinks_list
drinks_list = []
Perhaps define drink_lists outside of save_d (if not already done) as an empty list:
drinks_list = []
def save_d(added_drink_ent, top):
# append to drink_lists here
ok maybe I'm wrong but in save_d function, you start by using global variable drinks_list, and next line you set it to empty.
So everytime you use the function, you erase the previous list before you add something into it.
Hope this help

Show the Instagram post when the URL to this post is entered (Python | Tkinter)

I have created a GUI using tkinter where the user can paste an Instagram post URL. When the link is inserted, I want this image (i.e. the Instagram post) to be displayed next to the text field before the "Run" button is pressed (it is also be possible to create a button to show the image). Unfortunately, I have no idea how to do this.One idea would be that I download the particular image and then display it in this GUI. However, I think it would take too long to download and display each image. I also want the process to happen in the background. I think when an Instagram post needs to be downloaded, a web browser is opened for that (At least if you go by this post here).
I've left you a snippet of the GUI here.
Note: It's not the whole code, the different buttons are already linked with functions.
import tkinter as tk
from tkinter import *
from tkinter import ttk
root = tk.Tk()
root.geometry("440x105")
# Label
li = ttk.Label(root, text="Post URL")
li.grid(row=0, column=0)
li = ttk.Label(root, text="Some Input")
li.grid(row=0, column=2)
li = ttk.Label(root, text="Some list")
li.grid(row=1, column=0)
li = ttk.Label(root, text="Some Input 2")
li.grid(row=1, column=2)
# Input
url_text = StringVar()
e1 = ttk.Entry(root, textvariable=url_text)
e1.insert(0, "Instagram Post URL")
e1.grid(row=0, column=1)
# Dropdown Menu
OptionList = [
"1",
"2",
"3"
]
some_list = StringVar()
e3 = ttk.OptionMenu(root, some_list, *OptionList).place(x=48, y=23.5, width=110)
some_input = StringVar()
e2 = ttk.Entry(root, textvariable=some_input)
e2.insert(0, "")
e2.grid(row=0, column=3)
some_input2 = StringVar()
e4 = ttk.Entry(root, textvariable=some_input2)
e4.insert(0, "")
e4.grid(row=1, column=3)
# Buttons
b1_text = tk.StringVar()
b1 = ttk.Button(root, textvariable=b1_text, width=12, command="run") # "Run" is linked to another function
b1_text.set("Run")
b1.grid(row=2, column=1, pady=(15, 10))
b2 = ttk.Button(root, text="Button 2", width=12)
b2.grid(row=2, column=2, pady=(15, 10))
b3 = ttk.Button(root, text="Exit", width=12, command="exit")
b3.grid(row=2, column=3, pady=(15, 10))
root.mainloop()

How do I know the name of the button that called current function? [duplicate]

This question already has answers here:
Getting the widget that triggered an Event?
(3 answers)
Closed 3 years ago.
I'm learning python 3.7 and tkinter.
I want the function to know the name of the button that called it.
from tkinter import *
from random import randint
import inspect
def nay():
caller = inspect.stack()[1][3] # doesn't work
caller["text"] = "no"
def yay():
caller = inspect.stack()[1][3] # doesn't work
caller["text"] = "yes"
window = Tk()
randno = randint(0,1)
if randno ==1 :
b1Sel = yay
b2Sel = nay
else:
b1Sel = nay
b2Sel = yay
b1 = Button(window, text="???", command=b1Sel, width=10, height=5, font=font)
b2 = Button(window, text="???", command=b2Sel, width=10, height=5, font=font)
b1.pack(side=LEFT, padx=0)
b2.pack(side=RIGHT, padx=0)
window.mainloop()
I want to create a function that can distinguish which button called it.
One way to do is by using using lambda function
b1 = Button(window, text="A", command=lambda: action(1), width=10, height=5)
Try this code:
def action(num):
print(num)
b1 = Button(window, text="A", command=lambda: action(1), width=10, height=5)
b2 = Button(window, text="B", command=lambda: action(2), width=10, height=5)

Using a loop to create multiple drop down menus

I am trying to use a loop to create multiple drop down menus based on an entry in a entry text box after submit is pressed. I have never worked with tkinter before so I am not sure if I am doing this correctly. Any help would be appreciated. the code I have below is what I have but it causes the program to enter into some kind of infinite loop
from Tkinter import *
def callback():
numQues = E1.get()
i = 0
while i < numQues:
variable = StringVar(top)
variable.set("Short Answer") # default value
w = OptionMenu(top, variable, "Short Answer", "Multiple Choice", "Fill in the Blank",
"True of False", "Mathcing", "Ordering")
w.grid(row = i+1, column=0)
i = i+1
top = Tk()
top.geometry("600x600")
L1 = Label(top, text="How many questions will the quiz be?")
L1.grid(row=0, column=0)
E1 = Entry(top, bd = 5)
E1.grid(row=0, column=1)
MyButton1 = Button(top, text="Submit", width=10, command=callback)
MyButton1.grid(row=1, column=1)
top.mainloop()

tkinter (unsure of my error possibly due to .destroy())

from Tkinter import *
import random
menu = Tk()
subpage = Tk()
entry_values = []
population_values = []
startUpPage = Tk()
def main_menu(window):
window.destroy()
global menu
menu = Tk()
frame1 = Frame(menu)
menu.resizable(width=FALSE, height=FALSE)
button0 = Button(menu, text="Set Generation Zero Values", command=sub_menu(menu))
button1 = Button(menu, text="Display Generation Zero Values")
button2 = Button(menu, text="Run Model")
button3 = Button(menu, text="Export Data")
button4 = Button(menu, text="Exit Program", command=menu.destroy)
button0.grid(row=0, column=0, sticky=W)
button1.grid(row=2, column=0, sticky=W)
button2.grid(row=3, column=0, sticky=W)
button3.grid(row=4, column=0, sticky=W)
button4.grid(row=5, column=0, sticky=W)
menu.mainloop()
def sub_menu(window):
global subpage
window.destroy()
subpage = Tk()
subpage.resizable(width=FALSE, height=FALSE)
#defining sub page items
button5 = Button(subpage, text="Save Generation Data",command = main_menu(subpage))
juveniles_label0 = Label(subpage,text="Juveniles")
adults_label1 = Label(subpage,text="Adults")
seniles_label2 = Label(subpage,text="Seniles")
population_label3 = Label(subpage,text="Popultation")
survival_rate_label4 = Label(subpage,text="Survival Rate (Between 0 and 1)")
entry0 = Entry(subpage)
entry1 = Entry(subpage)
entry2 = Entry(subpage)
entry3 = Entry(subpage)
entry4 = Entry(subpage)
entry5 = Entry(subpage)
button4.grid(row=1, column= 6, sticky=E)
juveniles_label0.grid(row=0, column=1)
adults_label1.grid(row=0, column=2)
seniles_label2.grid(row=0, column=3)
population_label3.grid(row=1, column=0)
survival_rate_label4.grid(row=2, column=0)
entry0.grid(row=1, column=1)
entry1.grid(row=1, column=2)
entry2.grid(row=1, column=3)
entry3.grid(row=2, column=1)
entry4.grid(row=2, column=2)
entry5.grid(row=2, column=3)
#add entry 6 7 8
subpage.mainloop()
main_menu(subpage)
main_menu(startUpPage)
I'm very new to coding and stackoverflow. I am trying to create a GUI that has a main page which will be opened first and a sub page which will be opened by clicking a button which will be stored in the main page. my issue is that I have no clue why it isn't opening my main page. my thought is that it is something to do with the .destroy() or something similar. any help would be much appreciated.
As a general rule, you should create exactly one instance of Tk for the life of your program. That is how Tkinter is designed to be used. You can break this rule when you understand the reasoning behind it, though there are very few good reasons to break the rule.
The simplest solution is to implement your main menu and your sub menu as frames, which you've already done. To switch between them you can simply destroy one and (re)create the other, or create them all ahead of time and then remove one and show the other.
For example, the following example shows how you would create them ahead of time and simply swap them out. The key is that each function needs to return the frame, which is saved in a dictionary. The dictionary is used to map symbolic names (eg: "main", "sub", etc) to the actual frames.
def main_menu(root):
menu = Frame(root)
button0 = Button(menu, text="Set Generation Zero Values",
command=lambda: switch_page("sub"))
...
return menu
def sub_menu(root):
subpage = Frame(root)
button5 = Button(subpage, text="Save Generation Data",
command = lambda: switch_page("main"))
...
return subpage
def switch_page(page_name):
slaves = root.pack_slaves()
if slaves:
# this assumes there is only one slave in the master
slaves[0].pack_forget()
pages[page_name].pack(fill="both", expand=True)
root = Tk()
pages = {
"main": main_menu(root),
"sub": sub_menu(root),
...
}
switch_page("main")
root.mainloop()
For a more complex object-oriented approach see Switch between two frames in tkinter
heres some code that does what you want.. make a window, destroy it when button is clicked and then make a new window...
from Tkinter import *
import random
def main_menu():
global root
root = Tk()
b = Button(root,text='our text button',command = next_page)
b.pack()
def next_page():
global root,parent
parent = Tk()
root.destroy()
new_b = Button(parent,text = 'new Button',command=print_something)
new_b.pack()
def print_something():
print('clicked')
main_menu()
root.mainloop()
parent.mainloop()
ps. ive done this in python3 so keep that in mind though it wouldnt be a problem in my opinion

Categories