Tkinter dropdown Menu with keyboard shortcuts? - python

I would like to have a Dropdown Menu in Tkinter, that includes the shortcut key associated with this command. Is this possible?
How would I also add the underline under a certain character, to allow for Alt-F-S (File->Save)?

import tkinter as tk
import sys
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
menubar = tk.Menu(self)
fileMenu = tk.Menu(menubar, tearoff=False)
menubar.add_cascade(label="File", underline=0, menu=fileMenu)
fileMenu.add_command(label="Exit", underline=1,
command=quit, accelerator="Ctrl+Q")
self.config(menu=menubar)
self.bind_all("<Control-q>", self.quit)
def quit(self, event):
print("quitting...")
sys.exit(0)
if __name__ == "__main__":
app = App()
app.mainloop()

Maybe
from tkinter import *
import tkinter.filedialog as filed
root = Tk()
root.title("My Python Tkinter Application")
root.minsize(800,600)
def openfile():
fn = filed.askopenfilename(filetypes=[("Text Files","*.txt")], title="Open File")
f = open(fn, "r").read()
print(f)
def init():
menu = Menu(root)
filemenu = Menu(menu)
filemenu.add_command(label="Open (⌘O)", command=openfile)
menu.add_cascade(label="File", menu=filemenu)
root.config(menu=menu)
def key():
print("Key Pressed: "+repr(event.char))
root.bind("<Key>", key)

In this code press ctrl+e to exit the programmme
from tkinter import *
class MainApp:
def __init__(self, root):
self.root = root
self.menubar = Menu(self.root)
self.fileMenu = Menu(self.menubar, tearoff=False)
self.menubar.add_cascade(label="File", menu=self.fileMenu)
self.fileMenu.add_command(label="Exit", accelerator="Ctrl+E")
self.root.config(menu=self.menubar)
self.root.bind_all("<Control-e>", lambda event: self.root.quit())
self.root.mainloop()
if __name__ == "__main__":
MainApp(Tk())

Related

tkinter display new frame from menu

I'm trying to write my fisrt script in python & tkinter.
I block to display a new frame from a function (def onDisplay) when a click is made from menu bar button, but nothing append.
No error is display :-(
The new frame is made with dynamic checkboxes from text files:
txt file:
item1
item2
...
item100
A screen of the GUI:
Here my code:
from tkinter import Tk, Frame, Menu, Checkbutton, Text, TOP, BOTH, X, N, LEFT, BooleanVar
from tkinter.ttk import Frame, Label, Entry
import glob
class Example(Frame):
def __init__(self):
super().__init__()
self.initUI()
#self.display_srv()
def initUI(self):
self.master.title("Submenu")
menubar = Menu(self.master)
self.master.config(menu=menubar)
fileMenu = Menu(menubar)
submenu = Menu(fileMenu)
submenu.add_command(label="lst1", command=self.onDisplay)
submenu.add_command(label="lst2")
submenu.add_command(label="lst3")
fileMenu.add_cascade(label='Listing', menu=submenu, underline=0)
fileMenu.add_separator()
fileMenu.add_command(label="Exit", underline=0, command=self.onExit)
menubar.add_cascade(label="File", underline=0, menu=fileMenu)
#The frame i tried to display
def onDisplay(self):
self.master.title("display it")
self.pack(fill=BOTH, expand=True)
frame1 = Frame(self)
frame1.pack(fill=X)
path = '/root/liste/*.txt'
files=glob.glob(path)
count = 0
for file in files:
with open(file, 'r') as lst_file:
for item in lst_file:
# Need to split all item by 10
Checkbutton(self, text=item.rstrip()).grid(row=count//10, column=count%10)
count += 1
def onClick(self):
if self.var.get() == True:
self.master.title("Checkbutton")
else:
self.master.title("")
def onExit(self):
self.quit()
def main():
root = Tk()
root.geometry("850x550+300+300")
app = Example()
root.mainloop()
if __name__ == '__main__':
Many thanks for any help
Regards,
The main problem is that you're mixing grid and pack in the same parent container. You are calling pack on frame1 but you are calling grid on the checkbuttons, and they both have a master or parent of self.
That can't work, because each of grid and pack will try to resize the container according to it's rules, triggering the other one to reconfigure according to it's rules, and so on until the end of time.
So, simply changing your call of .grid(...) to .pack(...) on the checkbuttons will fix that problem.
My guess is that you intended to put the checkbuttons inside frame1. If that's the case, you need to specify frame1 as the master for the checkbuttons. For readability and ease of debugging I also recommend placing the call to grid on a separate line. With that, you can continue to use grid for the checkbuttons and pack for everything else.
cb = Checkbutton(frame1, text=item.rstrip())
cb.grid(row=count//10, column=count%10)
I posted the correct code:
from tkinter import Tk, Frame, Menu, Checkbutton, Text, TOP, BOTH, X, N, LEFT, BooleanVar
from tkinter.ttk import Frame, Label, Entry
import glob
class Example(Frame):
def __init__(self):
super().__init__()
self.initUI()
#self.display_srv()
def initUI(self):
self.master.title("Submenu")
menubar = Menu(self.master)
self.master.config(menu=menubar)
fileMenu = Menu(menubar)
submenu = Menu(fileMenu)
submenu.add_command(label="lst1", command=self.onDisplay)
submenu.add_command(label="lst2")
submenu.add_command(label="lst3")
fileMenu.add_cascade(label='Listing', menu=submenu, underline=0)
fileMenu.add_separator()
fileMenu.add_command(label="Exit", underline=0, command=self.onExit)
menubar.add_cascade(label="File", underline=0, menu=fileMenu)
def onDisplay(self):
self.master.title("display it")
self.pack(fill=BOTH, expand=True)
frame1 = Frame(self)
frame1.pack(fill=X)
path = '/root/liste/*.txt'
files=glob.glob(path)
count = 0
for file in files:
with open(file, 'r') as lst_file:
for item in lst_file:
cb = Checkbutton(frame1, text=item.rstrip())
cb.grid(row=count//10, column=count%10)
count += 1
def onClick(self):
if self.var.get() == True:
self.master.title("Checkbutton")
else:
self.master.title("")
def onExit(self):
self.quit()
def main():
root = Tk()
root.geometry("850x550+300+300")
app = Example()
root.mainloop()
if __name__ == '__main__':
main()

Text editor with Tkinter Python 3

I am trying to build a text editor with different tabs, and each one is a file, but the problem is that when I try to save the file, it doesn't read nothing, it creates a new file with no content. Before I didn't have the Tab class and it worked, but the problem was that it saved all the files with the same content.
Here is the code:
from tkinter import *
from tkinter import filedialog, ttk
import os
class App():
def __init__(self):
title = 'New document'
self.root = Tk()
self.root.geometry('300x200')
self.root.iconbitmap('icon.ico')
self.root.title(title)
self.tabs = {'ky': 0}
self.notebook = ttk.Notebook(self.root)
self.notebook.pack(expand = True, fill= 'both')
menubar = Menu(self.root)
# create a pulldown menu, and add it to the menu bar
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label="New...", command=self.generate_tab)
filemenu.add_command(label="Open", command = self.open_file)
filemenu.add_command(label="Save", command= self.save_file)
filemenu.add_separator()
filemenu.add_command(label="Exit", command= self.root.quit)
menubar.add_cascade(label="File", menu = filemenu)
editmenu = Menu(menubar, tearoff=0)
editmenu.add_command(label="Undo")
editmenu.add_command(label="Redo")
editmenu.add_separator()
menubar.add_cascade(label="Edit", menu=editmenu)
self.root.config(menu=menubar)
def open_file(self):
file = open(filedialog.askopenfilename(), 'r+')
text_value = file.read()
self.textWidget.delete(1.0, "end-1c")
self.textWidget.insert("end-1c", text_value)
title = os.path.basename(file.name)
self.root.title(title)
file.close()
def add_tab(self, name):
tab = Tab(self.notebook, name)
print(name)
self.notebook.add(tab, text=name)
def save_file(self):
self.get_tab().save_tab()
def get_tab(self):
tab = Tab(self.notebook, 'Document ' + str(self.notebook.index('current')))
return tab
def generate_tab(self):
if self.tabs['ky'] < 20:
self.tabs['ky'] += 1
self.add_tab('Document ' + str(self.tabs['ky']))
def run(self):
self.root.mainloop()
class Tab(Frame):
def __init__(self, root, name):
Frame.__init__(self, root)
self.root = root
self.name = name
self.textWidget = Text(self)
self.textWidget.pack(expand=True, fill='both')
def save_tab(self):
print(self.textWidget.get("1.0", 'end-1c'))
file = open(filedialog.asksaveasfilename() + '.txt', 'w+')
file.write(self.textWidget.get("1.0", 'end-1c'))
print(os.path.basename(file.name))
#title = os.path.basename(file.name)
file.close()
if __name__ == '__main__':
app1 = App()
app1.run()
Problem lies with your get_tab method. It doesn't actually return the object that represents the currently open tab. It returns a new tab that has no content.
In order to fix your problem you need to keep a record of the tabs you've created. I've created a 'workable' version that adds the object of each tab to a list when they are created. This way if you are currently in "Document 3" and press save, it will get the Tab object that relates to document 3.
from tkinter import *
from tkinter import filedialog, ttk
import os
class App():
def __init__(self):
title = 'New document'
self.root = Tk()
self.root.geometry('300x200')
#self.root.iconbitmap('icon.ico')
self.root.title(title)
self.tabs = {'ky': 0}
#Keep a record of the open tabs in a list.
self.tab_list = []
self.notebook = ttk.Notebook(self.root)
self.notebook.pack(expand = True, fill= 'both')
menubar = Menu(self.root)
# create a pulldown menu, and add it to the menu bar
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label="New...", command=self.generate_tab)
filemenu.add_command(label="Open", command = self.open_file)
filemenu.add_command(label="Save", command= self.save_file)
filemenu.add_separator()
filemenu.add_command(label="Exit", command= self.root.quit)
menubar.add_cascade(label="File", menu = filemenu)
editmenu = Menu(menubar, tearoff=0)
editmenu.add_command(label="Undo")
editmenu.add_command(label="Redo")
editmenu.add_separator()
menubar.add_cascade(label="Edit", menu=editmenu)
self.root.config(menu=menubar)
def open_file(self):
file = open(filedialog.askopenfilename(), 'r+')
text_value = file.read()
self.textWidget.delete(1.0, "end-1c")
self.textWidget.insert("end-1c", text_value)
title = os.path.basename(file.name)
self.root.title(title)
file.close()
def add_tab(self, name):
tab = Tab(self.notebook, name)
print(name)
self.notebook.add(tab, text=name)
self.tab_list.append(tab)
def save_file(self):
tab_to_save = self.get_tab()
print(tab_to_save)
tab_to_save.save_tab()
def get_tab(self):
print(self.notebook.index('current'))
#Get the tab object from the tab_list based on the index of the currently selected tab
tab = self.tab_list[self.notebook.index('current')]
return tab
def generate_tab(self):
if self.tabs['ky'] < 20:
self.tabs['ky'] += 1
self.add_tab('Document ' + str(self.tabs['ky']))
def run(self):
self.root.mainloop()
class Tab(Frame):
def __init__(self, root, name):
Frame.__init__(self, root)
self.root = root
self.name = name
self.textWidget = Text(self)
self.textWidget.pack(expand=True, fill='both')
def save_tab(self):
print(self.textWidget.get("1.0", 'end-1c'))
file = open(filedialog.asksaveasfilename() + '.txt', 'w+')
file.write(self.textWidget.get("1.0", 'end-1c'))
print(os.path.basename(file.name))
#title = os.path.basename(file.name)
file.close()
if __name__ == '__main__':
app1 = App()
app1.run()

initialising Basic GUI in Python (using tkinter)

I'm trying to make a menu but this just shows a blank GUI, what have i done wrong?
from tkinter import *
class GUI:
def __init__(self, master):
menu = Menu(master)
master.config(menu=menu)
submenu = Menu(menu)
menu.add_cascade(label="File", menu=submenu)
subMenu.add_command(label="Nothing", command=SayNothing)
subMenu.add_command(label="Exit", command=quit)
def SayNothing(self):
print("Nothing")
root = Tk()
app = GUI(root)
root.mainloop()
EDIT: I fixed a typo which now makes it display the 'File' but it doesn't show the submenus correctly
When mispellings and scoping are corrected, it works just fine:
from tkinter import *
class GUI:
def __init__(self, master):
menu = Menu(master)
master.config(menu=menu)
subMenu = Menu(menu)
menu.add_cascade(label="File", menu=subMenu)
subMenu.add_command(label="Nothing", command=self.SayNothing)
subMenu.add_command(label="Exit", command=quit)
def SayNothing(self):
print("Nothing")
root = Tk()
app = GUI(root)
root.mainloop()
subMenu should be consistently spelled
command=self.SayNothing, not command=SayNothing
First off, submenu is case sensitive. So you must reference it as submenu not subMenu unless you re-define it. In addition, you defined SayNothing after you referenced it.
This should solve all your problems.
from tkinter import *
def SayNothing():
print("Nothing")
class GUI:
def __init__(self, master):
menu = Menu(master)
master.config(menu=menu)
subMenu = Menu(menu)
menu.add_cascade(label="File", menu=subMenu)
subMenu.add_command(label="Nothing", command=SayNothing)
subMenu.add_command(label="Exit", command=quit)
root = Tk()
app = GUI(root)
root.mainloop()

Two windows: First Login after that main program

i have this program
class loginWindow():
def __init__(self, master):
self.master = master
self.frame = Frame(master)
master.title(u"Geometry Calc - Login")
Button(master, text="Login", command=self.login).pack()
def login(self):
self.newWindow = Toplevel(self.master)
main(self.newWindow)
self.master.withdraw()
class main():
def __init__(self, master):
# Nastavení nového okna
master.title(u"Geometry Calc") # Nadpis
master.geometry("695x935") # Rozmery v px
master.config(background="white")
master.resizable(width=FALSE, height=FALSE) # Zakážeme změnu rozměrů uživatelem - zatím..
menubar = Menu(master)
helpmenu = Menu(menubar, tearoff=0)
helpmenu.add_command(label="Konec", command=master.quit)
menubar.add_cascade(label="Soubor", menu=helpmenu)
helpmenu = Menu(menubar, tearoff=0)
helpmenu.add_command(label="O programu", command=self.createAbout)
menubar.add_cascade(label="Pomoc", menu=helpmenu)
master.config(menu=menubar)
canvas = Canvas(master, width=691, height=900)
canvas.pack(expand=1, fill=BOTH)
self.showImage(canvas, 347, 454, "geometry_table.jpg")
root = Tk()
app = loginWindow(root)
root.mainloop()
`
and i have this problem. When i run my program, i can see login window, when i hit login button I get window main, but window login is only withdrawed. So when i close window main my program still run. And i need make this. First run program main, but will be invisible or something. And i see only login window (maybe Toplevel). When i hit button login the window loginWindow will get destroy() and the window main will be visible
You can use Toplevel for login window and withdraw , deiconify methods to hide and show root window respectively.
Check the following code:
from Tkinter import *
class loginWindow(Toplevel):
def __init__(self, title, parent):
Toplevel.__init__(self, parent)
# Save parent reference to use it
self.parent = parent
self.parent.title(u"Geometry Calc - Login")
Button(self, text="Login", command=self.login).pack()
def login(self):
access = True # Used to test if a user can login.
if access:
# Close Toplevel window and show root window
self.destroy()
self.parent.deiconify()
else:
self.parent.quit()
class main(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
self.title(u"Geometry Calc") # Nadpis
self.geometry("695x935") # Rozmery v px
self.config(background="white")
self.resizable(width=FALSE, height=FALSE) # Zakážeme změnu rozměrů uživatelem - zatím..
menubar = Menu(self)
helpmenu = Menu(menubar, tearoff=0)
helpmenu.add_command(label="Konec", command=self.quit)
menubar.add_cascade(label="Soubor", menu=helpmenu)
helpmenu = Menu(menubar, tearoff=0)
helpmenu.add_command(label="O programu", command=self.createAbout)
menubar.add_cascade(label="Pomoc", menu=helpmenu)
self.config(menu=menubar)
canvas = Canvas(self, width=691, height=900)
canvas.pack(expand=1, fill=BOTH)
# Hide root window
self.withdraw()
# Lunch login window
loginWindow('Frame', self)
def createAbout(self):
pass
def quit(self):
self.destroy()
app = main()
app.mainloop()
If youn want to use 2 Toplevel windows for login and main app, root window should be hidden:
class loginWindow(Toplevel):
def __init__(self, title, parent):
Toplevel.__init__(self, parent)
...
def login(self):
if access:
# Close Toplevel window and lunch root window
self.destroy()
main()
class main(Toplevel):
def __init__(self, *args, **kwargs):
Toplevel.__init__(self, *args, **kwargs)
...
root = Tk()
root.withdraw()
loginWindow('title', root)
root.mainloop()

Tkinter Unknown Option -menu

I keep getting the error:
_tkinter.TclError: unknown option "-menu"
My MWE looks like:
from tkinter import *
def hello():
print("hello!")
class Application(Frame):
def createWidgets(self):
self.menuBar = Menu(master=self)
self.filemenu = Menu(self.menuBar, tearoff=0)
self.filemenu.add_command(label="Hello!", command=hello)
self.filemenu.add_command(label="Quit!", command=self.quit)
def __init__(self, master):
Frame.__init__(self, master)
self.pack()
self.createWidgets()
self.config(menu=self.menuBar)
if __name__ == "__main__":
root = Tk()
ui = Application(root)
ui.mainloop()
I'm on OS X 10.8 using python 3. Why am I getting the unknown option error?
self.config(menu=self.menuBar)
menu is not a valid configuration option for Frame.
Perhaps you meant to inherit from Tk instead?
from tkinter import *
def hello():
print("hello!")
class Application(Tk):
def createWidgets(self):
self.menuBar = Menu(master=self)
self.filemenu = Menu(self.menuBar, tearoff=0)
self.filemenu.add_command(label="Hello!", command=hello)
self.filemenu.add_command(label="Quit!", command=self.quit)
self.menuBar.add_cascade(label="File", menu=self.filemenu)
def __init__(self):
Tk.__init__(self)
self.createWidgets()
self.config(menu=self.menuBar)
if __name__ == "__main__":
ui = Application()
ui.mainloop()

Categories

Resources