I am new to tkinter and have big problem with the GUI. My idea is to create a Menubar here and I have it already implemented (below you can find main.py and menu.py).
Unfortunately, when I run the program only a very, very small window appears. It's so small that I can't really see it. But I don't understand why. What did I do wrong here?
import tkinter as tk
from menu import Menu
#from toolbar import Toolbar
#from content import Content
class MainApplication(tk.Frame):
def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
self.parent = parent
self.menu = Menu(self, background="yellow")
# Toolbar and Content not implemented yet
# self.toolbar = Toolbar(self, height=25, background="green")
# self.content = Content(self, background="red")
self.menu.pack()
#self.toolbar.pack()
#self.content.pack()
if __name__ == "__main__":
root = tk.Tk()
root.title("Editor")
app = MainApplication(root)
app.pack()
root.config(menu=app.menu.menubar)
root.mainloop()
That's the menu.py:
import tkinter as tk
class Menu(tk.Frame):
def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
self.parent = parent
self.menubar = tk.Menu(self)
self.create_file_menu(self.menubar)
self.create_edit_menu(self.menubar)
self.create_view_menu(self.menubar)
self.create_about_menu(self.menubar)
def create_file_menu(self, parent):
self.file_menu = tk.Menu(parent, tearoff=False)
self.menubar.add_cascade(label="File", menu=self.file_menu)
# Commands
self.file_menu.add_command(label="New", accelerator="Ctrl+N", command=new_callback)
self.file_menu.add_command(label="Open", accelerator="Ctrl+O", command=open_callback)
self.file_menu.add_command(label="Save", accelerator="Ctrl+S", command=save_callback)
self.file_menu.add_command(label="Save as", accelerator="Shift+Ctrl+S", command=saveas_callback)
self.file_menu.add_separator()
self.file_menu.add_command(label="Exit", accelerator="Alt+F4", command=exit_callback)
def create_edit_menu(self, parent):
self.edit_menu = tk.Menu(parent, tearoff=False)
self.menubar.add_cascade(label="Edit", menu=self.edit_menu)
# Commands
self.edit_menu.add_command(label="Undo", accelerator="Ctrl+Z", command=undo_callback)
self.edit_menu.add_command(label="Redo", accelerator="Ctrl+Y", command=redo_callback)
self.edit_menu.add_separator()
self.edit_menu.add_command(label="Cut", accelerator="Ctrl+X", command=cut_callback)
self.edit_menu.add_command(label="Copy", accelerator="Ctrl+C", command=copy_callback)
self.edit_menu.add_command(label="Paste", accelerator="Ctrl+V", command=paste_callback)
self.edit_menu.add_separator()
self.edit_menu.add_command(label="Find", accelerator="Ctrl+F", command=find_callback)
self.edit_menu.add_separator()
self.edit_menu.add_command(label="Select all", accelerator="Ctrl+A", command=selectall_callback)
def create_view_menu(self, parent):
self.view_menu = tk.Menu(parent, tearoff=False)
self.menubar.add_cascade(label="View", menu=self.view_menu)
def create_about_menu(self, parent):
self.about_menu = tk.Menu(parent, tearoff=False)
self.menubar.add_cascade(label="About", menu=self.about_menu)
# Commands
self.about_menu.add_command(label="About", command=about_callback)
self.about_menu.add_command(label="Help", command=help_callback)
def new_callback():
pass
def open_callback():
pass
def save_callback():
pass
def saveas_callback():
pass
def exit_callback():
pass
def undo_callback():
pass
def redo_callback():
pass
def cut_callback():
pass
def copy_callback():
pass
def paste_callback():
pass
def find_callback():
pass
def selectall_callback():
pass
def about_callback():
pass
def help_callback():
pass
I am not knowledgeable with the use of super()
. I have replaced it with tk.Frame
and made a few other changes which is accompanied with explanation/comment. See the revised codes given below. For the revised menu.py, you have to append the relevant sections from where I left off for the code to work (save display space).
I was able to get a non-zero width Tk window when the script was executed. Hope this solution helps you answer your question.
Revised Main.py
import tkinter as tk
from menu import Menu
class MainApplication(tk.Frame):
def __init__(self, parent, *args, **kwargs):
#super().__init__(parent, *args, **kwargs) #replaced with below sentence
tk.Frame.__init__(self, parent, *args, **kwargs) #added
self.parent = parent
#self.menu = Menu(self, background="yellow") #replaced with below 3 sentences
self.menu = Menu(self) #added: Instantiate the class Menu as self.menu
self.menubar = self.menu.menubar #added: relate the local variable for menubar(i.e. self.menubar) with the menubar variable in the instance self.menu.
self.menubar.configure(background = 'yellow') #added, configure the background
# If you comment the above 3 sentences and uncomment the below,
# you will get the same window
"""self.menubar = tk.Menu(self.parent, background="yellow")
self.create_file_menu(self.menubar)
self.create_edit_menu(self.menubar)
self.create_view_menu(self.menubar)
self.create_about_menu(self.menubar)
def create_file_menu(self, parent):
self.file_menu = tk.Menu(parent, tearoff=False)
self.menubar.add_cascade(label="File", menu=self.file_menu)
def create_edit_menu(self, parent):
self.edit_menu = tk.Menu(parent, tearoff=False)
#self.menubar.add_cascade(label="Edit", menu=self.edit_menu)
def create_view_menu(self, parent):
self.view_menu = tk.Menu(parent, tearoff=False)
self.menubar.add_cascade(label="View", menu=self.view_menu)
def create_about_menu(self, parent):
self.about_menu = tk.Menu(parent, tearoff=False)
self.menubar.add_cascade(label="About")"""
if __name__ == "__main__":
root = tk.Tk()
root.title("Editor")
app = MainApplication(root)
#app.pack() # this caused the zero width Window
root.configure(menu=app.menu.menubar)
root.mainloop()
Revised menu.py (Relevant part) :
import tkinter as tk
class Menu(tk.Frame):
def __init__(self, parent, *args, **kwargs):
#super().__init__(parent, *args, **kwargs) #replaced with below sentence
tk.Frame.__init__(self, parent, *args, **kwargs) #added
self.parent = parent
self.menubar = tk.Menu(self)
As I said in comments, apparently one can't attach a tk.Menu
to a tk.Frame
and have it things work correctly—however a workaround using tk.Menubutton
was suggested, so here's a modified version of your menu.py
that demonstrates how to implement said method of overcoming that limitation.
Basically each top menu item is now a tk.Menubtton
. The choices (picks) underneath each one are still separate tk.Menu
s as before. I also used the grid
layout manager to arrange them in a single row. You can probably do the same thing with pack
, but as I mentioned, I'm not familiar with it. Besides, there's no harm in an independent tk.Frame
using a different layout manager than its parent does.
No changes were made or required to your main.py
file. I put all those dummy callback functions you added to menu.py
into a separate callbacks.py
file which is now import
ed it near the beginning in the revised version of the file below.
Modified menu.py
:
import tkinter as tk
from callbacks import * # all the dummy callback functions...
class Menu(tk.Frame):
def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
self.create_file_menu()
self.create_edit_menu()
self.create_view_menu()
self.create_about_menu()
def create_file_menu(self):
self.file_menu = tk.Menubutton(self, text='File')
picks = tk.Menu(self.file_menu)
self.file_menu.config(menu=picks)
# Commands
picks.add_command(label='New', accelerator='Ctrl+N', command=new_callback)
picks.add_command(label='Open', accelerator='Ctrl+O', command=open_callback)
picks.add_command(label='Save', accelerator='Ctrl+S', command=save_callback)
picks.add_command(label='Save as', accelerator='Shift+Ctrl+S', command=saveas_callback)
picks.add_separator()
picks.add_command(label='Exit', accelerator='Alt+F4', command=exit_callback)
self.file_menu.grid(row=0, column=0)
def create_edit_menu(self):
self.edit_menu = tk.Menubutton(self, text='Edit')
picks = tk.Menu(self.edit_menu)
self.edit_menu.config(menu=picks)
# Commands
picks.add_command(label='Undo', accelerator='Ctrl+Z', command=undo_callback)
picks.add_command(label='Redo', accelerator='Ctrl+Y', command=redo_callback)
picks.add_separator()
picks.add_command(label='Cut', accelerator='Ctrl+X', command=cut_callback)
picks.add_command(label='Copy', accelerator='Ctrl+C', command=copy_callback)
picks.add_command(label='Paste', accelerator='Ctrl+V', command=paste_callback)
picks.add_separator()
picks.add_command(label='Find', accelerator='Ctrl+F', command=find_callback)
picks.add_separator()
picks.add_command(label='Select all', accelerator='Ctrl+A', command=selectall_callback)
self.edit_menu.grid(row=0, column=1)
def create_view_menu(self):
self.view_menu = tk.Menubutton(self, text='View')
picks = tk.Menu(self.view_menu)
self.view_menu.config(menu=picks)
# Commands
submenu = tk.Menu(picks)
picks.add_cascade(label='Views', menu=submenu)
submenu.add_command(label='View 1', command=lambda: None)
submenu.add_command(label='View 2', command=lambda: None)
self.view_menu.grid(row=0, column=2)
def create_about_menu(self):
self.about_menu = tk.Menubutton(self, text='About')
picks = tk.Menu(self.about_menu)
self.about_menu.config(menu=picks)
# Commands
picks.add_command(label='About', command=about_callback)
picks.add_command(label='Help', command=help_callback)
self.about_menu.grid(row=0, column=3)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.