I'm having trouble figuring out how to close a python tkinter window menu when clicking on the root of the menu, ie."File".
I was hoping there was just a command option available when instantiating the menu but it appears as though that is not the case. Also I know that there is an unpost method I can use to get rid of the menu but I don't know how I would trigger it on root menu click.
Edit:
Since Bryan said that my menus should be acting the same as any other menus in my os I decided to put together an example of how I'm doing menus. Maybe I am doing something wrong here but on ubuntu in every other program if I click on the root of the menu it will close it again. In this program it does not close when clicking on the root, only when clicking elsewhere on the screen does the menu close.
import tkinter as tk
import tkinter.messagebox
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.title("App Here")
self.window_menu = tk.Menu(self)
self.filemenu = tk.Menu(self.window_menu, tearoff=0)
self.build_window_menu()
self.config(menu=self.window_menu)
def build_window_menu(self):
self.window_menu.add_cascade(label="File", menu=self.filemenu)
self.filemenu.add_command(label='alert', command=self._handle_menualert)
def _handle_menualert(self):
tk.messagebox.showwarning(
"Menu Stuff",
"I am menu alert!"
)
if __name__ == '__main__':
app = App()
app.mainloop()
Related
I use tkinter and CTK:
I have created a page for login and I want to stop or use this page when the user is logged in, I want to show a new window and I want to resume the window when I want? How can I do that, I didn't know how to make it
I'll bite. Here's an example application that opens a second window when the user clicks a button on the main window, and disables interaction with the main window until the second window is closed.
Some configuration has been omitted for brevity, and I'm not using CTk here because I don't know how you've implemented it in your specific application - however, it should be easy enough to modify this example to work with CTk.
import tkinter as tk
from tkinter import ttk
class App(tk.Tk):
def __init__(self):
super().__init__()
self.open_button = ttk.Button(
self,
text='Open 2nd Window',
command=self.modal
)
self.open_button.pack()
def modal(self):
self.window = tk.Toplevel(self) # create new window
# bind a handler for when the user closes this window
self.window.protocol('WM_DELETE_WINDOW', self.on_close)
# disable interaction with the main (root) window
self.attributes('-disabled', True)
self.close_button = ttk.Button(
self.window,
text='Close Modal',
command=self.on_close
)
self.close_button.pack()
def on_close(self):
# re-enable interaction the root window
self.attributes('-disabled', False)
# close the modal window
self.window.destroy()
if __name__ == '__main__':
app = App()
app.mailoop() # run the app
In the future:
Provide code that shows you made a good-faith effort to solve the problem on your own
Don't post the same question multiple times within hours - if you need to make changes, edit the original question
If you mean you want to open up another window to do something before going back to the original window, you should consider using message box. Here is a link that goes over the types of messageboxes: https://docs.python.org/3/library/tkinter.messagebox.html.
I am opening other windows from a single tkinter button as shown here:
https://www.pythontutorial.net/tkinter/tkinter-toplevel/
The code shown there is
import tkinter as tk
from tkinter import ttk
class Window(tk.Toplevel):
def __init__(self, parent):
super().__init__(parent)
self.geometry('300x100')
self.title('Toplevel Window')
ttk.Button(self,
text='Close',
command=self.destroy).pack(expand=True)
class App(tk.Tk):
def __init__(self):
super().__init__()
self.geometry('300x200')
self.title('Main Window')
# place a button on the root window
ttk.Button(self,
text='Open a window',
command=self.open_window).pack(expand=True)
def open_window(self):
window = Window(self)
window.grab_set()
if __name__ == "__main__":
app = App()
app.mainloop()
If I run this program, it is not possible to hit the "Open a window" button twice to get two Toplevel instances. I would like to get as many instances as I like to with only one button. Is this possible somehow?
Consider this line of code:
window.grab_set()
This is setting a grab on the first window that is created. That means that all events from both the keyboard and the mouse are funneled to the first window that is created. That means you can no longer click on the button in the root window until the grab has been removed. Note that if the window is destroyed, the grab is automatically removed.
Grabs are typically used when creating a modal dialog -- a dialog which requires user input before the program can continue. By doing a grab, you insure that the user can't interact with the main program until they've interacted with the dialog.
The solution is simple: remove the call to window.grab_set() if your goal is to be able to open multiple windows which can all be used at the same time.
Simply remove window.grab_set(). The grab_set() method routes all events for this application to this widget. Whatever events generated like button-click or keypress is directed to another window.
def open_window(self):
window = Window(self)
How would I go about writing a command that fully closes the currently open tkinter programm. There are already a ton of threads regarding this, but I have been unable to find a solution that reliably closes all open tkinter windows. In my scenario, I am adding menus to each window with the option to close the current window, as well as close the whole programm. While closing the current window always works, closing the whole programm only works sporadically.
Things I have tried:
using root.quit() frequently leads to the "Python not responding" windows error message.
using root.destroy() will close the root window, and all toplevel windows, if I have not clicked on anything in them. Once I do use a toplevel window, it will not be ended by the root.destroy() command anymore.
using mytoplevel.destroy() will reliably close the currently active toplevel window.
I have written a simplified version of the code I am using, however, the windows don't do anything here, so the destroy command will always work.
import tkinter as tk
class MainWindow(tk.Frame):
def __init__(self, master = None):
b = tk.Button(master, text="Type_1", command=self.window_type_1)
b.pack()
self.load_menu(root)
tk.Frame.__init__(self, master)
def close(self, parent):
parent.destroy()
def window_type_1(self):
top = tk.Toplevel()
top.minsize(width = 600, height = 500)
self.load_menu(top)
def load_menu(self, parent):
menubar = tk.Menu(parent, tearoff=False)
parent.config(menu=menubar)
start_menu = tk.Menu(menubar, tearoff=False)
if parent == root:
start_menu.add_command(label="close", command=lambda: self.close(parent))
menubar.add_cascade(label="File", menu=start_menu)
else:
start_menu.add_command(label="Window close", command=lambda: self.close(parent))
start_menu.add_command(label="Programm close", command=lambda: self.close(root))
menubar.add_cascade(label="File", menu=start_menu)
root = tk.Tk()
mainwindow = MainWindow(master = root)
mainwindow.mainloop()
Calling destroy on the root window is generally the right solution, and is specifically the right solution in your example program. Destroying the root window will cause mainloop to exit, so unless you have more code after the call to mainloop and/or more code running in a separate thread, the program must exit.
How do you make a button open a duplicate window of the main page in a new window?
What would the python code be to do this with Tkinter?
For clarification, in notepad++ when you right click on the tab that you are in, it shows you a whole menu.
Then, there is a dropdown menu with an option that says, open in a new instance or move to a new instance.
This would then open the tab you selected into a new tab/window.
I haven't tried anything yet but I did look up about how to do this type of thing and there were no results on what exactly I wanted to do.
Can you try to show me an example of how what I need to do can be done?
Code:
Found Here
The simplest solution is to make your window be a subclass of Toplevel. Then, each time you need a new window, create a new instance of the class.
You can then leave the root window blank and hide it so that you only see your custom windows. It's important to make sure that you destroy the root window after the user has deleted the last application window, or else you'll end up with an invisible window that will be hard to kill.
Here is a bit of a contrived example:
import tkinter as tk
class AppWindow(tk.Toplevel):
def __init__(self, root):
tk.Toplevel.__init__(self, root)
self.root = root
menubar = tk.Menu(self)
windowMenu = tk.Menu(menubar)
windowMenu.add_command(label="New Window", command=self.new_window)
windowMenu.add_command(label="Quit", command=root.destroy)
menubar.add_cascade(label="Window", menu=windowMenu)
self.configure(menu=menubar)
self.text = tk.Text(self)
self.vsb = tk.Scrollbar(self, orient="vertical", command=self.text.yview)
self.text.configure(yscrollcommand=self.vsb.set)
self.vsb.pack(side="right", fill="y")
self.text.pack(side="left", fill="both", expand=True)
# call a function to destroy the root window when the last
# instance of AppWindow is destroyed
self.wm_protocol("WM_DELETE_WINDOW", self.exit_on_last_window)
def new_window(self):
AppWindow(self.root)
def exit_on_last_window(self):
"""Destroy the root window when no other windows exist"""
self.destroy()
if not any([window.winfo_exists() for window in self.root.winfo_children()]):
self.root.destroy()
def quit(self):
self.root.destroy()
# create the root, then hide it. The app will create its
# own windows as Toplevels
root = tk.Tk()
root.withdraw()
# create the first window, then start the event loop
AppWindow(root)
tk.mainloop()
The gtk FileChooserWidget shows a context menu on right-click with "add to bookmarks", "show hidden files", and "show size column" options. I would like to override this menu with a custom menu.
Creating a menu on right-click from other gtk widgets (window, eventbox) is easy and there are a lot of tutorials out there showing how to do it.
I can't seem to get events from a gtk filechooser widget, however. The "on_button_press_event" callback in the following code never gets called:
#!/usr/bin/env python
import gtk
class file_chooser_test():
def __init__(self):
window = gtk.Window()
window.connect("delete_event", lambda w,e: gtk.main_quit())
chooser = gtk.FileChooserWidget()
chooser.set_size_request(600, 400)
chooser.add_events(gtk.gdk.BUTTON_PRESS_MASK)
chooser.connect("button-press-event", self.on_button_press_event)
window.add(chooser)
window.show_all()
gtk.main()
def on_button_press_event(self, widget, event=None):
print "event is: ", event
if __name__ == "__main__":
test = file_chooser_test()
Can anyone shed any light on how to override the default right-click menu on the GTK FileChooserWidget?
Thanks!