binding menu item to notebook tab in python - python-3.x

I would like to bind a menu item to a notebook frame using a function(like gotofirst tab).
for instance a menu: file with 3 item such that if I click on the 3rd item in the menu file, the 3rd tab in the notebook should be selected or it should go to the 3rd tab and at the same time not see other tabs(hide them or disable them).
from tkinter import *
from tkinter import ttk
### defining functions ###
def GotoFirst():
pass
def Gotosecond():
pass
def Gotothird():
pass
### Frame and notebook ###
root = Tk()
root.geometry('1000x700+1000+40')
root.resizable(FALSE,FALSE)
root.rowconfigure(0,weight=1)
root.columnconfigure(0,weight=1)
root.title("Test Fieldbook")
fieldbook = ttk.Notebook(root)
f1 = ttk.Frame(fieldbook);
f2 = ttk.Frame(fieldbook);
f3 = ttk.Frame(fieldbook);
fieldbook.add(f1, text="1st")
fieldbook.add(f2, text="2nd")
fieldbook.add(f3, text="3rd")
fieldbook.grid(row=0, column=0, sticky=(N,W,S,E))
### Creating menu bar ###
menubar=Menu(root)
filemenu=Menu(menubar)
filemenu.add_command(label="Help Docs",command=GotoFirst)
filemenu.add_command(label="About ESB",command=Gotosecond)
filemenu.add_command(label="About ESB",command=Gotothird)
menubar.add_cascade(label="Help",menu=filemenu)
root.config(menu=menubar)
root.mainloop()

You can use the select method:
fieldbook.select(0)
and
fieldbook.select(f1)
do the same thing.

Thank you for the hint, I manage to make it work.
fieldbook.tab(f1, state='normal')
fieldbook.select(f1)
fieldbook.hide(f3)
with .tab() I can change the state as I wish and with .hide() I can make a specific tab disappear momentarily and call it back anytime with .add()

Related

How to remove focus from Text block by clicking outside it

I want to create a program using tkinter. The goal is to remove the focus from Text widget by clicking somewhere outside it. I've tried this:
import tkinter as tk
root = tk.Tk()
txt = tk.Text(root)
txt.pack()
root.bind('<Button-1>', lambda event: root.focus_set())
#txt.bind('<Button-1>', lambda event: txt.focus_set()) <- it doesn't work with this too
root.mainloop()
But this just sets focus to root every time i press B1 (in both variants). Help, please!
You could detect the current widget under the mouse coordinates and use this to determine if you should focus on root or not:
def click_event(event):
x,y = root.winfo_pointerxy() # get the mouse position on screen
widget = root.winfo_containing(x,y) # identify the widget at this location
if (widget == ".text_widget") == False: # if the mouse is not over the text widget
root.focus() # focus on root
text_widget = tk.Text(root, name="text_widget")
text_widget.pack()
root.bind("<Button-1>", click_event)

get value from event in an entrybox

#I want to put the selected item from combobox in the merk_entry. and the selected item from the listbox(omschrijving) in model_entry.
.get() or insert aren't working in this function.
I tried both of them. Also Comboboxselected.
I dont know how fix this.
Thanks in advance.
from tkinter import *
from tkinter.ttk import Combobox
window=Tk()
window.geometry("500x500")
wagenmerk=["BMW","Mercedes","Audi"]
Bmw=["Bmw 1 reeks","Bmw 5 reeks Berline","Bmw 7 reeks"]
Mercedes=["A-klasse","B-klasse","Eqc","C-klasse"]
Audi=["A1","A3","A4"]
def toon_info(evt):
teller=1
merk_info=automerk_entry.get()
print(merk_info)
if merk_info == "BMW":
omschrijving.delete(0,END)
for line in Bmw:
omschrijving.insert(teller,Bmw[teller-1])
teller+=1
elif merk_info=="Mercedes":
omschrijving.delete(0,END)
for line in Mercedes:
omschrijving.insert(teller,Mercedes[teller-1])
teller+=1
elif merk_info=="Audi":
omschrijving.delete(0,END)
for line in Audi:
omschrijving.insert(teller,Audi[teller-1])
teller+=1
automerk_text=Label(text="automerk")
merk_text=Label(text="merk")
model_text=Label(text="model")
prijs_text=Label(text="prijs")
automerk_text.place(x=15,y=70)
merk_text.place(x=280,y=100)
model_text.place(x=280,y=120)
prijs_text.place(x=280,y=140)
merk=StringVar()
model=StringVar()
prijs=StringVar()
merk_entry=Entry(textvariable=merk,width="25")
model_entry=Entry(textvariable=model,width="25")
prijs_entry=Entry(textvariable=prijs,width="25")
merk_entry.place(x=320,y=100)
model_entry.place(x=320,y=125)
prijs_entry.place(x=320,y=150)
automerk_entry=Combobox(window,values=wagenmerk,width=30)
automerk_entry.bind("<<ComboboxSelected>>",toon_info)
automerk_entry.place(x=70,y=70)
omschrijving=Listbox(window,width=30,height=10)
omschrijving.place(x=70,y=100)
#button
bereken=Button(window,text="toon",width="30",height="2",command=toon_info,bg="grey")
bereken.place(x=70,y=270)
You have not set the two Entry widgets to take the change in values. Your Comboboxselected works as expected. Do the following changes to reflect the selection of the Combobox widget and the Listbox widget to the 2 Entry widgets:
def toon_info(evt):
teller=1
merk_info=automerk_entry.get()
merk.set(merk_info) # set the StringVar variable (assigned to the merk_entry widget)
...
...
Bind the Listbox widget:
def set_item(evt):
model.set(omschrijving.get(omschrijving.curselection()[0]))
omschrijving.bind('<<ListboxSelect>>', set_item)
And lastly, the Button-bereken is not set to send or activate any event/evt. So the callback function (under the option command) has to be changed
This is how I fixed it.
def set_item(evt):
model_entry.delete(0,END)
cur_selection=omschrijving.curselection()
if len(cur_selection)>0:
model.set(omschrijving.get(cur_selection[0]))

How can I change the state of a menu with a button inside tkinter?

I want to make a unit converter in tkinter. I made two drop-down menus; the first one allows the user to select the unit they want to convert from, and the second one allows them to choose the unit they want to convert to. I want to disable all the options that do not make sense in the second menu after they have selected an option in the first one (if they want to convert kilograms it would not make sense to choose centimeters in the second menu)
I have tried to use a StringVar() to change the state of the menu, but it is not working. I have no idea of what to do next. I have been using the documentation of Tutorialspoint, but I cannot find anything that works (first time using tkinter).
import tkinter as tk
root = tk.Tk()
root.geometry('600x600')
my_var = tk.StringVar()
my_var.set('active')
unit_1 = tk.Menubutton(root,text='This is the first menu button',bg='white',activebackground='#2E64FE',activeforeground='#FFFFFF')
menu_1 = tk.Menu(unit_1)
unit_1.config(menu=menu_1)
menu_1.add_command(label='Inches',command= lambda: my_var.set('disabled') )
menu_1.add_command(label='Kilograms')
unit_2 = tk.Menubutton(root,text='This is the second menu button',bg='white',activebackground='#2E64FE',activeforeground='#FFFFFF')
menu_2 = tk.Menu(unit_2)
unit_2.config(menu=menu_2)
menu_2.add_command(label='Centimeters')
menu_2.add_command(label='Pounds',state= my_var.get())
unit_1.place(relx=0.03,rely=0.08,relheight=0.04,relwidth=0.45)
unit_2.place(relx=0.52,rely=0.08,relheight=0.04,relwidth=0.45)
root.mainloop()
Here I am trying to make the button 'Inches' in the first menu to disable the button 'Pounds' in the second menu, but when I click on 'Inches' nothing happens to 'Pounds'.
tk.StringVar() is used to change text on something, for example if you want to have a button with dynamic text, you may want to use a tk.StringVar() for that.
What you want to do is something different; you want to change the configuration of a label. So you need to find the element and adjust its state:
import tkinter as tk
root = tk.Tk()
root.geometry('600x600')
my_var = tk.StringVar()
my_var.set('active')
unit_1 = tk.Menubutton(root,text='This is the first menu button',bg='white',activebackground='#2E64FE',activeforeground='#FFFFFF')
menu_1 = tk.Menu(unit_1)
unit_1.config(menu=menu_1)
menu_1.add_command(label='Inches', command=lambda: disable_pounds())
menu_1.add_command(label='Kilograms', command=lambda: disable_centimeters())
unit_2 = tk.Menubutton(root,text='This is the second menu button',bg='white',activebackground='#2E64FE',activeforeground='#FFFFFF')
menu_2 = tk.Menu(unit_2)
unit_2.config(menu=menu_2)
menu_2.add_command(label='Centimeters')
menu_2.add_command(label='Pounds',state= my_var.get())
unit_1.place(relx=0.03,rely=0.08,relheight=0.04,relwidth=0.45)
unit_2.place(relx=0.52,rely=0.08,relheight=0.04,relwidth=0.45)
def disable_pounds():
menu_2.entryconfig("Pounds", state="disabled")
menu_2.entryconfig("Centimeters", state="active")
def disable_centimeters():
menu_2.entryconfig("Pounds", state="active")
menu_2.entryconfig("Centimeters", state="disabled")
root.mainloop()

Is there a way to change a buttons colour when the button is made in a function?

I have made a button within a function and when the button is clicked a command is run to change the button color.
However this does not work as I get an error, but I need to create the button in the function.
It works when the button is defined outside the function and I assume the issue is that the data is forgotten after a function ends.
from tkinter import *
root = Tk()
def ColourChange(Letter):
NameButton.config(bg = "red")
def Change():
Letter = "a"
NameButton=Button(root, text = "This", command = lambda Letter = Letter:
ColourChange(Letter)
NameButton.pack()
Change()
When I click the button I would like the color of the background to change.
The actual error is
NameButton.config(bg="red") NameError: name 'NameButton' is not defined"
Set your global variable so it can be access by other function.Also move NameButton.pack() to new line after NameButton=Button(root,text="This",command=lambda Letter=Letter: ColourChange(Letter)).
from tkinter import *
root=Tk()
def ColourChange(Letter):
NameButton.config(bg="red")
def Change():
global NameButton # global variable
Letter="a"
NameButton=Button(root,text="This",command=lambda Letter=Letter: ColourChange(Letter))
NameButton.pack()
#NameButton.pack()
Change()

Dropdown menu command execution

Is it possible to get a drop-down menu using python's tkinter modules which execute commands when clicked on?
# Imports tkinter
from tkinter import *
#creates a root, then a popup and a frame inside to work with
root = Tk()
popup = Toplevel()
popup_frame = Frame(popup)
#creates a labelframe to hold the label and menu
labelframe_example = LabelFrame(root, text="Title For Widget", pady=3, padx=3)
#label providing description about menu
Label(labelframe_example, text="Descriptive label", width=25, height=0).pack()
#options displayed in dropdown menu
options = ["Option1","Option2", "Option3"]
#gains the variable of what is in the menu
variable = StringVar(labelframe_example)
#sets the inital text for the menu, before an option is selected
variable.set("Pre-option text placeholder")
#places the dropdown menu in the labelframe, with the displayed text being whatever the variable is and calls the options, expands the menu to size of labelframe
OptionMenu(labelframe_example, variable, *options).pack(fill=BOTH, expand=1)
#packs frame
labelframe_example.pack()
#creates a function to destroy old frame inside the popup window and recreate it using the information for option 1
def executed_command_1(popup_frame):
popup_frame.destroy()
popup_frame = Frame(popup)
Label(popup_frame, text="Hey Look it worked, a new frame was created for option 1").pack()
#creates a function to destroy old frame inside the popup window and recreate it using the information for option 2
def executed_command_2(popup_frame):
popup_frame.destroy()
popup_frame = Frame(popup)
Label(popup_frame, text="Hey Look it worked, a new frame was created for option 2").pack()
#creates a function to destroy old frame inside the popup window and recreate it using the information for option 3
def executed_command_3(popup_frame):
popup_frame.destroy()
popup_frame = Frame(popup)
Label(popup_frame, text="Hey Look it worked, a new frame was created for option 3").pack()
#unsure how to actually make a way for option specific function to open
option_execution_button = Button(root, text="Open Option", width=25, padx=5, pady=5,
command=lambda:executed_command_1/2/3(popup_frame)).pack()
In other words, there are 2 windows, 1 window has a widget with a drop-down menu, and the other should update based on whichever option was selected, the button is not actually necessary if there is a way for this to happen without the button that would be fine too.
I just can't figure out a way to do it, any help is welcome.
Sorry if its hard to understand, if you don't understand I will attempt to clarify further.

Resources