Reputation: 3
I am creating a rouge-like text based adventure game in python using tkinter and I am trying to set up the GUI. I want the menu bar to appear after I enter the main game screen (so after the player clicks 'start game'). For some reason python can't find the menubar that I have defined when I call the function for it and I'm can't understand why.
I have been trying different methods and doing research on other forums for a few days now but I have yet to find an answer. I have tried: - Creating a function - trying to call it the variable from another class - renaming the object - checked the indentation - As far as I can see, it is fine
I have also tried creating the menubar normally and having it load when the program runs. (i.e. not in a function but in the 'init' part of the class.) This works but I want the menu bar to appear later and not at the start.
##Importing modules-------------------------------------------------------
#------------------------------------------------------------------------
import tkinter as tk
from tkinter import messagebox
#Setting up GUI ---------------------------------------------------------
#------------------------------------------------------------------------
#MainWindow
class FireofStromwarld(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title("The Fire of Stromwarld")
self.config(bg = 'grey')
#Centering Window
WindowWidth = 900
WindowHeight = 600
ScreenWidth = self.winfo_screenwidth()
ScreenHeight = self.winfo_screenheight()
xCoordinate = int((ScreenWidth / 2) - (WindowWidth / 2))
yCoordinate = int((ScreenHeight / 2) - (WindowHeight / 2))
self.geometry('{}x{}+{}+{}'.format(WindowWidth, WindowHeight, xCoordinate, yCoordinate))
self.resizable(width = False, height = False)
#Setting up container to hold all frames
frmContainer = tk.Frame(self)
frmContainer.config(width = 750,
height = 450,
bg = 'grey')
frmContainer.grid_propagate(0)
frmContainer.grid(row = 0, column = 0, padx = 75, pady = 75)
#Listing avaliable frames
self.frames = ['MainMenu', 'GameMenu']
self.frames[0] = MainMenu(parent = frmContainer, controller = self)
self.frames[1] = GameMenu(parent = frmContainer, controller = self)
self.frames[0].grid(row = 0, column = 0, sticky = 'nsew')
self.frames[1].grid(row = 0, column = 0, sticky = 'nsew')
self.ShowFrame(0)
#Menubar(The Problem Part)
self.menuBar = tk.Menu(self)
self.GameMenu = tk.Menu(self.menuBar, tearoff = 0)
self.GameMenu.add_command(label = 'Exit',
font = ('arial', 9),
command = self.quit)
self.menuBar.add_cascade(label = 'Game',
menu = self.GameMenu)
self.RemoveFunc()
def ShowFrame(self, pagename):
frame = self.frames[pagename]
frame.tkraise()
def CreateMenu(self):
NewMenu = self.menuBar
self.configure(menu = NewMenu)
def RemoveFunc(self):
emptyMenu = tk.Menu(self)
self.configure(menu = emptyMenu)
#MainMenu
class MainMenu(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.config(bg = 'grey')
#Objects on Main Menu
lblTitle = tk.Label(self,
text = "The Fire of Stromwarld",
font = ('Arial', 28, 'bold'),
fg = 'brown',
bg = 'grey',
justify = 'center')
btnStart = tk.Button(self,
text = "Start Game",
font = ('Arial',16),
bg = 'grey',
relief = 'flat',
command = lambda: controller.ShowFrame(1))
btnExit = tk.Button(self,
text = "Exit",
font = ('Arial',16),
bg = 'grey',
relief = 'flat',
width = 9,
command = self.quit)
#Positioning of Main Window Objects
lblTitle.grid(row = 0, column = 0, padx = 178, pady = 75)
btnStart.grid(row = 1, column = 0, pady = (50,20))
btnExit.grid(row = 2, column = 0)
#GameMenu
class GameMenu(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.config(bg = 'grey')
#Creating Menu Base
controller.CreateMenu()
#Objects on Game Menu
#Player and Monster Stat boxes
frmPlayerStats = tk.Frame(self,
width = 180,
height = 150,
borderwidth = 2,
relief = 'ridge')
frmPlayerStats.grid_propagate(0)
frmMonStats = tk.Frame(self,
width = 180,
height = 80,
borderwidth = 2,
relief = 'groove')
frmMonStats.grid_propagate(0)
#Player Stats
lblPlayerName = tk.Label(frmPlayerStats,
text = "Player:",
font = ('arial', 13))
lblPlayerLevel = tk.Label(frmPlayerStats,
text = "Lvl: 1",
font = ('arial', 10))
lblPlayerHPTitle = tk.Label(frmPlayerStats,
text = "HP: ",
font = ('arial', 10))
lblPlayerHPStats = tk.Label(frmPlayerStats,
text = "10 / 10",
font = ('arial', 10),
fg = 'green')
lblPlayerMPTitle = tk.Label(frmPlayerStats,
text = "MP: ",
font = ('arial', 10))
lblPlayerMPStats = tk.Label(frmPlayerStats,
text = "5 / 5",
font = ('arial', 10),
fg = 'blue')
lblPlayerBaseAttkTitle = tk.Label(frmPlayerStats,
text = "Attack: ",
font = ('arial', 10))
lblPlayerBaseAttkStats = tk.Label(frmPlayerStats,
text = "5",
font = ('arial', 10),
fg = 'red')
lblPlayerWeapTitle = tk.Label(frmPlayerStats,
text = "Weapon: ",
font = ('arial', 10))
lblPlayerWeapStats = tk.Label(frmPlayerStats,
text = "None | +2",
font = ('arial', 10))
lblPlayerArmTitle = tk.Label(frmPlayerStats,
text = "Armour: ",
font = ('arial', 10))
lblPlayerArmStats = tk.Label(frmPlayerStats,
text = "5",
font = ('arial', 10))
#Monster Stats
lblMonName = tk.Label(frmMonStats,
text = "Monster:",
font = ('arial', 11))
lblMonHPTitle = tk.Label(frmMonStats,
text = "HP: ",
font = ('arial', 9))
lblMonHPStats = tk.Label(frmMonStats,
text = "10 / 10",
font = ('arial', 9),
fg = 'green')
lblMonMPTitle = tk.Label(frmMonStats,
text = "MP: ",
font = ('arial', 9))
lblMonMPStats = tk.Label(frmMonStats,
text = "5 / 5",
font = ('arial', 9),
fg = 'blue')
#Main Objects
#Text display
txtMain = tk.Text(self,
width = 78,
height = 22,
borderwidth = 1,
relief = 'solid',
wrap = 'word',
cursor = 'left_ptr')
txtMain.grid_propagate(0)
scrlTxtMain = tk.Scrollbar(self)
txtMain.configure(yscrollcommand = scrlTxtMain.set)
scrlTxtMain.configure(command = txtMain.yview)
#User input
lblentUserInput = tk.Label(self,
text = '>>>',
font = ('arial', 9),
bg = 'white')
entUserInput = tk.Entry(self,
font = ('arial', 9),
relief = 'sunken',
justify = 'left',
width = 69,
borderwidth = 2)
btnUserInput = tk.Button(self,
text = "Enter",
font = ('arial', 7),
relief = 'groove',
width = 7)
#Action Buttons
btnAction1 = tk.Button(self,
text = "Attack",
font = ('arial', 10),
relief = 'raised',
cursor = 'X_cursor',
width = 10,
height = 2)
btnAction1.grid_propagate(0)
btnAction2 = tk.Button(self,
text = "Special",
font = ('arial', 10),
relief = 'raised',
cursor = 'cross_reverse',
width = 10,
height = 2,)
btnAction2.grid_propagate(0)
btnAction3 = tk.Button(self,
text = "Heal",
font = ('arial', 10),
relief = 'raised',
cursor = 'heart',
width = 10,
height = 2)
btnAction3.grid_propagate(0)
btnAction4 = tk.Button(self,
text = "Run",
font = ('arial', 10),
relief = 'raised',
cursor = 'right_side',
width = 10,
height = 2)
btnAction4.grid_propagate(0)
#Inventory
lblInventoryTitle = tk.Label(self,
text = 'Inventory:' + ' ' * 27,
font = ('arial',11, 'italic'),
bg = 'white')
lstbInventory = tk.Listbox(self,
font = ('arial', 9),
width = 23,
height = 11,
cursor = 'hand2')
scrllstbInventory = tk.Scrollbar(self)
lstbInventory.configure(yscrollcommand = scrllstbInventory.set)
scrllstbInventory.configure(command = lstbInventory.yview)
#Positioning of Game Objects
#Main object placements
txtMain.grid(row = 0, column = 0, rowspan = 30, columnspan = 10)
scrlTxtMain.grid(row = 0, column = 10, rowspan = 30, padx = (0, 1), sticky = 'nsw')
#Entry line placement
lblentUserInput.grid(row = 31, column = 0, columnspan = 2)
entUserInput.grid(row = 31, column = 2, columnspan = 6, sticky = 'w')
btnUserInput.grid(row = 31, column = 7, columnspan = 4, sticky = 'w')
#Action buttons placements
btnAction1.grid(row = 32, column = 3, padx = 15, pady = 20)
btnAction2.grid(row = 32, column = 4, padx = 15, pady = 20)
btnAction3.grid(row = 32, column = 5, padx = 15, pady = 20)
btnAction4.grid(row = 32, column = 6, padx = 15, pady = 20)
#Stats objects placenments
frmPlayerStats.grid(row = 0, column = 11, columnspan = 2, padx = 3)
lblPlayerName.grid(row = 0, column = 0, sticky = 'w')
lblPlayerLevel.grid(row = 0, column = 1, sticky = 'w')
lblPlayerHPTitle.grid(row = 1, column = 0, sticky = 'w')
lblPlayerHPStats.grid(row = 1, column = 1, sticky = 'w')
lblPlayerMPTitle.grid(row = 2, column = 0, sticky = 'w')
lblPlayerMPStats.grid(row = 2, column = 1, sticky = 'w')
lblPlayerBaseAttkTitle.grid(row = 3, column = 0, sticky = 'w')
lblPlayerBaseAttkStats.grid(row = 3, column = 1, sticky = 'w')
lblPlayerWeapTitle.grid(row = 4, column = 0, sticky = 'w')
lblPlayerWeapStats.grid(row = 4, column = 1, sticky = 'w')
lblPlayerArmTitle.grid(row = 5, column = 0, sticky = 'w')
lblPlayerArmStats.grid(row = 5, column = 1, sticky = 'w')
frmMonStats.grid(row = 1, column = 11, columnspan = 2, padx = 3, pady = 4)
lblMonName.grid(row = 0, column = 0, sticky = 'w')
lblMonHPTitle.grid(row = 1, column = 0, sticky = 'w')
lblMonHPStats.grid(row = 1, column = 1, sticky = 'w')
lblMonMPTitle.grid(row = 2, column = 0, sticky = 'w')
lblMonMPStats.grid(row = 2, column = 1, sticky = 'w')
#Inventory object placements
lblInventoryTitle.grid(row = 2, column = 11, columnspan = 2, padx = 3, pady = (4,0), sticky = 'w')
lstbInventory.grid(row = 3, column = 11, rowspan = 32, padx = (3,0), sticky = 'w')
scrllstbInventory.grid(row = 3, column = 12, rowspan = 32, sticky = 'nsw')
#Runnning Program -------------------------------------------------------
#------------------------------------------------------------------------
game = FireofStromwarld()
game.mainloop()
This is my first post on stackoverflow so I apologise if any of my formatting is a bit off, especially the code that I have shown. I can't seem to get it to highlight the python syntax properly.
I hope that someone can help me. Thank you! >.<
EDIT1 (29/03/2019): Here is the error I am getting:
Traceback (most recent call last):
File "C:\Users\***\Documents\Python\Games\FireofStromwarldv2.0\game_Main1.py", line 356, in <module>
game = FireofStromwarld()
File "C:\Users\***\Documents\Python\Games\FireofStromwarldv2.0\game_Main1.py", line 50, in __init__
self.frames[1] = GameMenu(parent = frmContainer, controller = self)
File "C:\Users\***\Documents\Python\Games\FireofStromwarldv2.0\game_Main1.py", line 130, in __init__
controller.CreateMenu()
File "C:\Users\***\Documents\Python\Games\FireofStromwarldv2.0\game_Main1.py", line 74, in CreateMenu
NewMenu = self.menuBar
File "C:\Users\***\AppData\Local\Programs\Python\Python36\lib\tkinter\__init__.py", line 2098, in __getattr__
return getattr(self.tk, attr)
AttributeError: '_tkinter.tkapp' object has no attribute 'menuBar'
[Finished in 0.8s]
The *** Are just to censor my User name.
Upvotes: 0
Views: 2042
Reputation: 47173
It is because you call controller.CreateMenu()
when creating GameMenu()
and in this moment the self.menuBar
used in controller.CreateMenu()
does not exist as self.menuBar
is created after GameMenu()
.
Try moving self.menuBar = tkMenu(self)
in __init__(...)
of class FireofStromwarld
somewhere before the statement self.frames[1] = GameMenu(parent = frmContainer, controller = self)
.
Upvotes: 1