Keep a menu open in Tkinter - python

I want to keep a menu cascade open, after a command button within the cascade is clicked. So it basically only closes when the user clicks anywhere else (like it would normally too). Can't seem to find a proper option or a method to open said menu in the callback. The invoke() function only works on buttons wihtin the cascade right? How would you go about that?

Yes, I know this was asked a long time ago, but I was curious if there was any way to accomplish this with tkinter, so I fiddled about for a while and figured out how to do it. I was unable to come up with a way to properly place the persistent menu where it was when it originally opened, but I have managed to make it persist in any location you request (I use upper-left corner of root window). And yes, I know this isn't a nice proper class based implementation, but I was just going for as simple a test as I could write without obscuring it with too many extraneous details.
try:
from tkinter import *
from tkinter.ttk import *
except:
from Tkinter import *
from ttk import *
root = Tk()
var = StringVar()
def menu_click(menu, item):
global root
var.set(item)
menu.post(root.winfo_rootx(), root.winfo_rooty())
root.option_add('*tearOff', False) # remove tearoff from all menus
Label(root, textvariable=var).pack() # just to give menu clicks some feedback
root.geometry('400x300')
menubar = Menu(root)
root['menu'] = menubar
menu_test = Menu(menubar)
menubar.add_cascade(menu=menu_test, label='Test')
menu_test.add_command(label='One', command=lambda: menu_click(menu_test, 'One'))
menu_test.add_command(label='Two', command=lambda: menu_click(menu_test, 'Two'))
menu_test.add_command(label='Three', command=lambda: menu_click(menu_test, 'Three'))
menu_cas = Menu(menu_test)
menu_test.add_cascade(menu=menu_cas, label='Four')
menu_cas.add_command(label='One', command=lambda: menu_click(menu_cas, 'Fourty One'))
menu_cas.add_command(label='Two', command=lambda: menu_click(menu_cas, 'Fourty Two'))
menu_cas.add_command(label='Three', command=lambda: menu_click(menu_cas, 'Fourty Three'))
root.mainloop()

Related

Customizing Button Commands in Python Tkinter

I've recently started learning how to use Tkinter. I'm working on the front-end for a small project to design an Enigma Machine, and a part of it involves creating a keyboard-like layout of buttons to simulate the plugboard. When clicking one button, I want it to go to a method I've created to handle all button presses and tell the method which letter the button corresponds to, and act accordingly. The main task right now is to make it so that pressing one button and then pressing another button after that draws a line between both buttons.
What I've added below is a scuffed version of the actual program to cut out repeated code like the button declarations.
from tkinter import *
from tkinter import ttk
from PIL import ImageTk, Image
class Steckerbrett:
root = Tk()
frm = ttk.Frame(root, padding=10)
frm.grid(row=0, column=0)
ttk.Label(frm, text="Enigma Machine").grid(column=0, row=0)
ttk.Label(frm, text="Steckerbrett").grid(column=0, row=1)
ttk.Label(frm, text="").grid(column=0, row=2)
# plugboard keys row 1
frm1 = ttk.Frame(root, padding=10)
frm1.grid(row=1, column=0)
ttk.Button(frm1, text="Q", command=connection).grid(column=0, row=0)
ttk.Button(frm1, text="W", command=connection).grid(column=1, row=0)
# i have declarations like this for all 26 letters
root.mainloop()
def connection(self, letter):
ttk.Label(self.frm, text=letter).grid(column=0, row=2)
sb = Steckerbrett()
The issue here is that since 'command' doesn't allow entering a function with arguments, I can't pass the letter to the function, and I can not make a custom method for every single button, because I would need to process first button presses and second button presses differently to make the connections. Is there a way to use a single function in the command but customize it to each button? Alternatively, if there isn't, are there any other solutions I can try? I am willing to try using other graphics packages as well.

Python Tkinter Gui Hide and show key bind

0 iq Question incoming, i wanna know is there a way i can show and hide a tkinter gui with insert key, ive searched online but wasnt able to find an answer, for example like csgo menus.
Thank you.
Please make sure to always include what you have tried and your research. Follow these guidelines to create a minimal reproducible example.
What you are trying to accomplish can be done with this Tkinter template:
from tkinter import *
root = Tk()
# Open new window
def launch():
global second
second = Toplevel()
second.title("Child Window")
second.geometry("400x400")
# Show the window
def show():
if event.keysym == "Insert"
second.deiconify()
# Hide the window
def hide():
if event.keysym == "Insert"
second.withdraw()
# Add Buttons
Button(root, text="launch Window", command=launch).pack(pady=10)
Button(root, text="Show", command=show).pack(pady=10)
Button(root, text="Hide", command=hide).pack(pady=10)
root.mainloop()

How can I combine this tkinter label and string into one window?

In a program I am working on there is a tkinter label/button which starts the card game (the program I am using) and a other window that has a string stating 'Welcome to the card game'.
Here is the tkinter section of the code:
import tkinter
window = tkinter.Tk()
print()
from tkinter import *
def quit():
global root
root.quit()
root = Tk()
while True:
label = tkinter.Label(window, text = "Welcome to the card game! (During name registration only use characters)").pack()
Button(root, text="Start Game", command=quit).pack()
root.mainloop()
However when I run the program they each appear in their own window screens when it would be more convenient for the user to have the options in one single window.
Is there anyway to merge them?
EDIT - (Having the button and text using root has fixed the problem.)
There is a lot going on here that should not be in such a small set of code.
Lets break it down.
First your imports. You are importing from tkinter multiple times. You only need to import once and you can use everything with the proper prefix. The preferred method is import tkinter as tk this way you don't overwrite any other imports or built in methods.
Next we need to get rid of one of your instances of Tk() as tkinter should only ever have one. For other windows use Toplevel().
In your quit function you do not need to define global as you are not assigning values here so the function will look in the global namespace for root.
Next Lets delete the empty print statement.
Next make sure both your label and button have the same container assigned to them. This is the reason why you are seeing them in different windows.
Next rename your function as quit is a built in method and should not be overwritten.
Lastly we remove the while statement as the mainloop() is already looping the Tk instance. You do not need to manage this yourself.
Here is what your code should look like (a 2nd window serves no purpose here):
import tkinter as tk
def root_quit():
root.quit()
root = tk.Tk()
tk.Label(root, text="Welcome to the card game! (During name registration only use characters)").pack()
tk.Button(root, text="Start Game", command=root_quit).pack()
root.mainloop()
Here is an example using Toplevel just so you can get an idea of how it is used.
import tkinter as tk
def root_quit():
root.quit()
def game_window():
top = tk.Toplevel(root)
tk.Button(top, text='exit', command=root_quit).pack()
root = tk.Tk()
tk.Label(root, text="Welcome to the card game! (During name registration only use characters)").pack()
tk.Button(root, text="Start Game", command=game_window).pack()
root.mainloop()

How do I get an attribute from a Combobox and put it into a variable?

I'm making a project in Tkinter Python and I want users to select an attribute from a Combobox widget and press a button and that attribute will be stored in a variable. I've searched all over the web, but I can't make heads or tails of the code and have no idea how to store this attribute. Can someone tell me how to do this
I've tried the .get thing... (module? widget?) but that is not working and as I said, the internet ain't no help.
This is my basic code with the window and the Combobox:
from tkinter import *
from tkinter import ttk
master = Tk()
ver = ttk.Combobox(master, state="readonly", values=["test1", "test2"]).pack()
Button(master, text="Run").pack()
master.mainloop()
I want to be able to store the selected item in the Combobox and put it in a variable.
pack returns None if you want to assign to a variable, you must do it on a separate line.
If you want action, Button requires a command key word arg to which you assign a callback.
After you have fixed the mistakes, you can use the get method on the Combobox:
import tkinter as tk
from tkinter import ttk
def print_selected():
print(combo.get())
master = tk.Tk()
combo = ttk.Combobox(master, state="readonly", values=["test1", "test2"])
combo.pack()
tk.Button(master, text="Run", command=print_selected).pack()
master.mainloop()

How do I disable keyboard input into an Entry widget, disable resizing of tkinter window and hide the console window?

I am making a calculator using tkinter and I wish to do the following:
Disable keyboard input for the Entry widget so that the user can only input through the buttons.
Even after disabling keyboard input for the Entry widget, I wish to be able to change the background and foreground of the widget.
I wish to hide the console window because it is totally useless in the use of this calculator.
I don't want to let the user resize the root window. How do I disallow the resizing of the root window?
Here is my code so far...
from tkinter import *
root = Tk()
root.title("Calculator")
root.config(background="black")
operator = ""
textVar = StringVar()
def valInput(number):
global operator
operator+=str(number)
textVar.set(operator)
display = Entry(root, textvariable=textVar, font=("Arial", 14, "bold"), bg="lightblue", fg="black", justify="right")
display.grid(row=0, column=0, columnspan=4)
btn7 = Button(root, font=("Arial", 12, "bold"), bg="orange", fg="red", text="7", command= lambda : valInput(7))
btn7.grid(row=1, column=0)
"""
And more buttons...
"""
root.mainloop()
As you can see, I can input into the Entry widget using buttons but later on, after the calculator is complete, if the user inputs characters like abcd... it will cause problems and show errors. How do I disallow keyboard entry so that I can avoid these errors?
I want to make my calculator a bit colorful. I changed the color of the root window, the buttons and also the color of the Entry widget. Is there any way to change the color of the widget even after it is disabled?
I don't need the console window while using this calculator. How do I hide it?
If I resize the root window, the calculator becomes ugly, besides, resizing the window isn't necessary. So how do I prevent the user from resizing the window?
To be able to disable keyboard input in Entry(args)
Set the state to disabled:
display = Entry(root, state=DISABLED)
To be able to disable the feature of resizing the tkinter window (so that you can't drag and stretch it.
root.resizable(0,0)
To be able to make the command prompt window disappear. (I just want the tkinter window.
Rename the file with a .pyw extension (assuming you are using windows)
Don't use from tkinter import * it's really not recommended because it pollutes the main namespace with every public name in the module. At best this makes code less explicit, at worst, it can (and it will) cause name collisions.
Have the right reflexes, use import tkinter or import tkinter as tk instead
this should work, you have to use the disabledbackground option :
import tkinter as tk
root = tk.Tk()
display = tk.Entry(root,font=('Arial', 20, 'bold'), disabledbackground='lightblue', state='disabled')
display.pack()
root.resizable(0,0)
root.mainloop()

Categories