Tkinter buttons bellow grid to close and save to file
Question:
I’m trying to create a grid of buttons that change colour with Tkinter.
from tkinter import *
class App():
def __init__(self, root):
self.root = root
buttonQ = Button(self.root, text = "Quit", command = endProgam())
buttonS = Button(self.root, text = "Save", command = saveToFile())
def Function(self):
self.grid = []
for i in range(5):
row = []
for j in range(5):
row.append(Button(self.root,width=6,height=3,command=lambda i=i, j=j: self.Click1(i, j),background='gray'))
row[-1].grid(row=i,column=j)
self.grid.append(row)
def Click1(self, i, j):
orig_color = self.grid[i][j].cget('bg')
#print(orig_color)
if orig_color=="red":
self.grid[i][j]["bg"]="gray"
else:
self.grid[i][j]["bg"]="red"
#self.grid[i][j]["bg"]="red"
#self.grid[i][j].configure(background="blue")
def endProgam(self):
# top.quit()
top.destroy()
def saveToFile(self):
# save matrix to file
top.destroy()
root = Tk()
app = App(root)
app.Function()
root.mainloop()
My problem is that I cannot add 2 buttons below the grid, one to quit and one to save into a file values based on the button colours (0-grey and 1-red as a matrix) and then quit.
File "--", line 37, in <module>
app = App(root)
File "--", line 6, in __init__
buttonQ = Button(self.root, text = "Quit", command = endProgam())
TypeError: endProgam() missing 1 required positional argument: 'self'
It’s my first time coding in Python with Tkinter, so please be gentle 🙂
Answers:
First, your indentation levels for your Class are off. The methods need to be indented another level or you’ll get a TypeError for each method.
Second, for buttonQ
and buttonS
, make sure you are referencing the instance of the class, i.e.:
buttonQ = Button(self.root, text = "Quit", command = endProgam)
buttonS = Button(self.root, text = "Save", command = saveToFile)
should be:
buttonQ = Button(self.root, text = "Quit", command = self.endProgam)
buttonS = Button(self.root, text = "Save", command = self.saveToFile)
(Note the use of self
)
As far as actually placing the buttons, I would recommend creating an additional frame to manage the layouts separately. You can create and place these just like widgets and it helps make managing the layouts much simpler.
For example:
class App():
def __init__(self, root):
self.root = root
self.TopFrame = Frame(root) # Create a top frame to place the original grid
self.BottomFrame = Frame(root) # Create a frame for the additional buttons
self.TopFrame.grid(row=0) # Place the Frame itself
self.BottomFrame.grid(row=6) # Place the new Frame directly below the first
# Changed to an instance variable to reference in Function method
buttonQ = Button(self.BottomFrame, text="Quit", command=self.endProgam)
buttonS = Button(self.BottomFrame, text="Save", command=self.saveToFile)
buttonS.grid(row=0, column=0, padx=10)
buttonQ.grid(row=0, column=1, padx=10)
def Function(self):
self.grid = []
for i in range(5):
row = []
for j in range(5):
row.append(Button(self.TopFrame,width=6,height=3,command=lambda i=i, j=j: self.Click1(i, j),background='gray'))
row[-1].grid(row=i,column=j)
self.grid.append(row)
Notice the new TopFrame
and BottomFrame
. The grid buttons are now sitting on the TopFrame
while the BottomFrame
contains the two new button widgets.
You’ll find that placing separate layout objects in its own frame will make managing more complex layouts much simpler.
I’m trying to create a grid of buttons that change colour with Tkinter.
from tkinter import *
class App():
def __init__(self, root):
self.root = root
buttonQ = Button(self.root, text = "Quit", command = endProgam())
buttonS = Button(self.root, text = "Save", command = saveToFile())
def Function(self):
self.grid = []
for i in range(5):
row = []
for j in range(5):
row.append(Button(self.root,width=6,height=3,command=lambda i=i, j=j: self.Click1(i, j),background='gray'))
row[-1].grid(row=i,column=j)
self.grid.append(row)
def Click1(self, i, j):
orig_color = self.grid[i][j].cget('bg')
#print(orig_color)
if orig_color=="red":
self.grid[i][j]["bg"]="gray"
else:
self.grid[i][j]["bg"]="red"
#self.grid[i][j]["bg"]="red"
#self.grid[i][j].configure(background="blue")
def endProgam(self):
# top.quit()
top.destroy()
def saveToFile(self):
# save matrix to file
top.destroy()
root = Tk()
app = App(root)
app.Function()
root.mainloop()
My problem is that I cannot add 2 buttons below the grid, one to quit and one to save into a file values based on the button colours (0-grey and 1-red as a matrix) and then quit.
File "--", line 37, in <module>
app = App(root)
File "--", line 6, in __init__
buttonQ = Button(self.root, text = "Quit", command = endProgam())
TypeError: endProgam() missing 1 required positional argument: 'self'
It’s my first time coding in Python with Tkinter, so please be gentle 🙂
First, your indentation levels for your Class are off. The methods need to be indented another level or you’ll get a TypeError for each method.
Second, for buttonQ
and buttonS
, make sure you are referencing the instance of the class, i.e.:
buttonQ = Button(self.root, text = "Quit", command = endProgam)
buttonS = Button(self.root, text = "Save", command = saveToFile)
should be:
buttonQ = Button(self.root, text = "Quit", command = self.endProgam)
buttonS = Button(self.root, text = "Save", command = self.saveToFile)
(Note the use of self
)
As far as actually placing the buttons, I would recommend creating an additional frame to manage the layouts separately. You can create and place these just like widgets and it helps make managing the layouts much simpler.
For example:
class App():
def __init__(self, root):
self.root = root
self.TopFrame = Frame(root) # Create a top frame to place the original grid
self.BottomFrame = Frame(root) # Create a frame for the additional buttons
self.TopFrame.grid(row=0) # Place the Frame itself
self.BottomFrame.grid(row=6) # Place the new Frame directly below the first
# Changed to an instance variable to reference in Function method
buttonQ = Button(self.BottomFrame, text="Quit", command=self.endProgam)
buttonS = Button(self.BottomFrame, text="Save", command=self.saveToFile)
buttonS.grid(row=0, column=0, padx=10)
buttonQ.grid(row=0, column=1, padx=10)
def Function(self):
self.grid = []
for i in range(5):
row = []
for j in range(5):
row.append(Button(self.TopFrame,width=6,height=3,command=lambda i=i, j=j: self.Click1(i, j),background='gray'))
row[-1].grid(row=i,column=j)
self.grid.append(row)
Notice the new TopFrame
and BottomFrame
. The grid buttons are now sitting on the TopFrame
while the BottomFrame
contains the two new button widgets.
You’ll find that placing separate layout objects in its own frame will make managing more complex layouts much simpler.