ttk buttons in python dict reference to the same object, generation problem?












1















I'm really confused about the problem I'm facing. I've spent some time trying to aisle the problem as much as I can, and here it is:



Im working with tkinter and ttk, and I want to create a grid of buttons, just like in this code:(Taken from https://www.edureka.co/community/1539/tkinter-grid-overlapping-issue)
TL;DR: Just a working calendar that has a button per day in a grid



from calendar import *
import datetime
try:
from tkinter import * # Python 3.x
except:
from Tkinter import * # Python 2.x


class Application(Frame):

def __init__(self, master=None):
Frame.__init__(self, master)
self.grid(row=0, column=0, sticky='news')

DateNow = datetime.datetime.now()
month = int(DateNow.month)
year = int(DateNow.year)
self.createDaysOfWeekLabels()
month_name = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
# Create frames and button controls for previous, current and next month.
self.frameList = # List that contains the frame objects.
self.buttonList = # List that contains the button objects.
amonth = month - 1
for i in range(3):
if amonth < 0:
amonth = 11
year -= 1
elif amonth == 12:
amonth = 1
year += 1

mFrame = Frame(self)
self.createMonth(mFrame, amonth, year)
self.frameList.append(mFrame)
mButton = Button(self, text=month_name[amonth-1])
mButton['command'] = lambda f=mFrame, b=mButton: self.showMonth(f, b)
mButton.grid(row=0, column=i)
# Grid each frame
mFrame.grid(row=2, column=0, columnspan=7, sticky='news')
if (i == 1):
mButton['relief'] = 'flat'
else:
# Remove all but the ith frame. More efficient to remove than forget and configuration is remembered.
mFrame.grid_remove()
self.buttonList.append(mButton)
amonth += 1

# Create year widget at top left of top frame
label = Label(self, text=year)#displaying year
label.grid(row=0, column=6)


def createDaysOfWeekLabels(self):
days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
for i in range(7):
label = Label(self, text=days[i])
label.grid(row = 1, column = i)

def showMonth(self, mFrame, mButton):
# Display all buttons normally
for button in self.buttonList:
button['relief'] = 'raised'

# Set this month's button relief to flat
mButton['relief'] = 'flat'

# Hide all frames
for frame in self.frameList:
frame.grid_remove()

mFrame.grid()

def createMonth(self, mFrame, month, year):
weekday, numDays = monthrange(year, month)
week = 0
for i in range(1, numDays + 1):
button = Button(mFrame, text = str(i), width=3)
button.grid(row = week, column = weekday)

weekday += 1

if weekday > 6:
week += 1
weekday = 0

mainWindow = Tk()
obj = Application(mainWindow)
mainWindow.mainloop()


then I tried to do something similar but using a dictionary whose key is a coordinate tuple and the value is the button(which has a frame as a parent), like this:



coords = {(0, 0):ttk.Button(self.frame_p1g), (0, 1): ttk.Button(self.frame_p1g)}


I just used this same dict for my grid, and this code down here, and it works perfectly:



x = 2
for i in coords.values():
i.grid(row=x, column=2)
x += 1


Image of the result



But as soon as I use a simple function to generate a grid automatically, and then place it in the grid, it doesn't work:



def make(width, height, element):
grid = {}
for y in range(height):
for x in range(width):
print ("X: " + str(x))
print ("Y: " + str(y))
grid[x, y] = element
return grid


Image with result



I tried to find the cause, but the only thing I could find was that the function seems to create exact same buttons, and somehow when I try to place them, every button gets the same row and column config:



Dict print from working dict



Dict print from bugged list



And this is the code that places each button(just pretty similar to the other, just using the lengh of the dict to know where to place them)



    self.p1g = make(int(self.size[0]), int(self.size[1]), ttk.Button(self.frame_p1g))
print(self.p1g)
x = 2
y = 2
for butt in self.p1g.values():
butt.grid(row=y, column=x)
x += 1
if x > (list(self.p1g.keys())[-1][0]):
x = 2
y += 1


The question: How can I make it work with a dict?(I really need those coordinates to reference the buttons)










share|improve this question


















  • 2





    I recommend by starting with a single function that creates the grid and does nothing else. You've posted too much extra code that isn't relevant to the question being asked, which makes it hard to read and understand. It's important to narrow the code down to the smallest Minimal, Complete, and Verifiable example possible.

    – Bryan Oakley
    Nov 21 '18 at 3:37













  • It references to the same object because make function operates on only one element, hence one element has one set of coordinates at a time. Is there a problem with creating buttons inside of the make instead of passing one? Looks like someone's inattention or I missed something.

    – CommonSense
    Nov 21 '18 at 8:03
















1















I'm really confused about the problem I'm facing. I've spent some time trying to aisle the problem as much as I can, and here it is:



Im working with tkinter and ttk, and I want to create a grid of buttons, just like in this code:(Taken from https://www.edureka.co/community/1539/tkinter-grid-overlapping-issue)
TL;DR: Just a working calendar that has a button per day in a grid



from calendar import *
import datetime
try:
from tkinter import * # Python 3.x
except:
from Tkinter import * # Python 2.x


class Application(Frame):

def __init__(self, master=None):
Frame.__init__(self, master)
self.grid(row=0, column=0, sticky='news')

DateNow = datetime.datetime.now()
month = int(DateNow.month)
year = int(DateNow.year)
self.createDaysOfWeekLabels()
month_name = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
# Create frames and button controls for previous, current and next month.
self.frameList = # List that contains the frame objects.
self.buttonList = # List that contains the button objects.
amonth = month - 1
for i in range(3):
if amonth < 0:
amonth = 11
year -= 1
elif amonth == 12:
amonth = 1
year += 1

mFrame = Frame(self)
self.createMonth(mFrame, amonth, year)
self.frameList.append(mFrame)
mButton = Button(self, text=month_name[amonth-1])
mButton['command'] = lambda f=mFrame, b=mButton: self.showMonth(f, b)
mButton.grid(row=0, column=i)
# Grid each frame
mFrame.grid(row=2, column=0, columnspan=7, sticky='news')
if (i == 1):
mButton['relief'] = 'flat'
else:
# Remove all but the ith frame. More efficient to remove than forget and configuration is remembered.
mFrame.grid_remove()
self.buttonList.append(mButton)
amonth += 1

# Create year widget at top left of top frame
label = Label(self, text=year)#displaying year
label.grid(row=0, column=6)


def createDaysOfWeekLabels(self):
days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
for i in range(7):
label = Label(self, text=days[i])
label.grid(row = 1, column = i)

def showMonth(self, mFrame, mButton):
# Display all buttons normally
for button in self.buttonList:
button['relief'] = 'raised'

# Set this month's button relief to flat
mButton['relief'] = 'flat'

# Hide all frames
for frame in self.frameList:
frame.grid_remove()

mFrame.grid()

def createMonth(self, mFrame, month, year):
weekday, numDays = monthrange(year, month)
week = 0
for i in range(1, numDays + 1):
button = Button(mFrame, text = str(i), width=3)
button.grid(row = week, column = weekday)

weekday += 1

if weekday > 6:
week += 1
weekday = 0

mainWindow = Tk()
obj = Application(mainWindow)
mainWindow.mainloop()


then I tried to do something similar but using a dictionary whose key is a coordinate tuple and the value is the button(which has a frame as a parent), like this:



coords = {(0, 0):ttk.Button(self.frame_p1g), (0, 1): ttk.Button(self.frame_p1g)}


I just used this same dict for my grid, and this code down here, and it works perfectly:



x = 2
for i in coords.values():
i.grid(row=x, column=2)
x += 1


Image of the result



But as soon as I use a simple function to generate a grid automatically, and then place it in the grid, it doesn't work:



def make(width, height, element):
grid = {}
for y in range(height):
for x in range(width):
print ("X: " + str(x))
print ("Y: " + str(y))
grid[x, y] = element
return grid


Image with result



I tried to find the cause, but the only thing I could find was that the function seems to create exact same buttons, and somehow when I try to place them, every button gets the same row and column config:



Dict print from working dict



Dict print from bugged list



And this is the code that places each button(just pretty similar to the other, just using the lengh of the dict to know where to place them)



    self.p1g = make(int(self.size[0]), int(self.size[1]), ttk.Button(self.frame_p1g))
print(self.p1g)
x = 2
y = 2
for butt in self.p1g.values():
butt.grid(row=y, column=x)
x += 1
if x > (list(self.p1g.keys())[-1][0]):
x = 2
y += 1


The question: How can I make it work with a dict?(I really need those coordinates to reference the buttons)










share|improve this question


















  • 2





    I recommend by starting with a single function that creates the grid and does nothing else. You've posted too much extra code that isn't relevant to the question being asked, which makes it hard to read and understand. It's important to narrow the code down to the smallest Minimal, Complete, and Verifiable example possible.

    – Bryan Oakley
    Nov 21 '18 at 3:37













  • It references to the same object because make function operates on only one element, hence one element has one set of coordinates at a time. Is there a problem with creating buttons inside of the make instead of passing one? Looks like someone's inattention or I missed something.

    – CommonSense
    Nov 21 '18 at 8:03














1












1








1








I'm really confused about the problem I'm facing. I've spent some time trying to aisle the problem as much as I can, and here it is:



Im working with tkinter and ttk, and I want to create a grid of buttons, just like in this code:(Taken from https://www.edureka.co/community/1539/tkinter-grid-overlapping-issue)
TL;DR: Just a working calendar that has a button per day in a grid



from calendar import *
import datetime
try:
from tkinter import * # Python 3.x
except:
from Tkinter import * # Python 2.x


class Application(Frame):

def __init__(self, master=None):
Frame.__init__(self, master)
self.grid(row=0, column=0, sticky='news')

DateNow = datetime.datetime.now()
month = int(DateNow.month)
year = int(DateNow.year)
self.createDaysOfWeekLabels()
month_name = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
# Create frames and button controls for previous, current and next month.
self.frameList = # List that contains the frame objects.
self.buttonList = # List that contains the button objects.
amonth = month - 1
for i in range(3):
if amonth < 0:
amonth = 11
year -= 1
elif amonth == 12:
amonth = 1
year += 1

mFrame = Frame(self)
self.createMonth(mFrame, amonth, year)
self.frameList.append(mFrame)
mButton = Button(self, text=month_name[amonth-1])
mButton['command'] = lambda f=mFrame, b=mButton: self.showMonth(f, b)
mButton.grid(row=0, column=i)
# Grid each frame
mFrame.grid(row=2, column=0, columnspan=7, sticky='news')
if (i == 1):
mButton['relief'] = 'flat'
else:
# Remove all but the ith frame. More efficient to remove than forget and configuration is remembered.
mFrame.grid_remove()
self.buttonList.append(mButton)
amonth += 1

# Create year widget at top left of top frame
label = Label(self, text=year)#displaying year
label.grid(row=0, column=6)


def createDaysOfWeekLabels(self):
days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
for i in range(7):
label = Label(self, text=days[i])
label.grid(row = 1, column = i)

def showMonth(self, mFrame, mButton):
# Display all buttons normally
for button in self.buttonList:
button['relief'] = 'raised'

# Set this month's button relief to flat
mButton['relief'] = 'flat'

# Hide all frames
for frame in self.frameList:
frame.grid_remove()

mFrame.grid()

def createMonth(self, mFrame, month, year):
weekday, numDays = monthrange(year, month)
week = 0
for i in range(1, numDays + 1):
button = Button(mFrame, text = str(i), width=3)
button.grid(row = week, column = weekday)

weekday += 1

if weekday > 6:
week += 1
weekday = 0

mainWindow = Tk()
obj = Application(mainWindow)
mainWindow.mainloop()


then I tried to do something similar but using a dictionary whose key is a coordinate tuple and the value is the button(which has a frame as a parent), like this:



coords = {(0, 0):ttk.Button(self.frame_p1g), (0, 1): ttk.Button(self.frame_p1g)}


I just used this same dict for my grid, and this code down here, and it works perfectly:



x = 2
for i in coords.values():
i.grid(row=x, column=2)
x += 1


Image of the result



But as soon as I use a simple function to generate a grid automatically, and then place it in the grid, it doesn't work:



def make(width, height, element):
grid = {}
for y in range(height):
for x in range(width):
print ("X: " + str(x))
print ("Y: " + str(y))
grid[x, y] = element
return grid


Image with result



I tried to find the cause, but the only thing I could find was that the function seems to create exact same buttons, and somehow when I try to place them, every button gets the same row and column config:



Dict print from working dict



Dict print from bugged list



And this is the code that places each button(just pretty similar to the other, just using the lengh of the dict to know where to place them)



    self.p1g = make(int(self.size[0]), int(self.size[1]), ttk.Button(self.frame_p1g))
print(self.p1g)
x = 2
y = 2
for butt in self.p1g.values():
butt.grid(row=y, column=x)
x += 1
if x > (list(self.p1g.keys())[-1][0]):
x = 2
y += 1


The question: How can I make it work with a dict?(I really need those coordinates to reference the buttons)










share|improve this question














I'm really confused about the problem I'm facing. I've spent some time trying to aisle the problem as much as I can, and here it is:



Im working with tkinter and ttk, and I want to create a grid of buttons, just like in this code:(Taken from https://www.edureka.co/community/1539/tkinter-grid-overlapping-issue)
TL;DR: Just a working calendar that has a button per day in a grid



from calendar import *
import datetime
try:
from tkinter import * # Python 3.x
except:
from Tkinter import * # Python 2.x


class Application(Frame):

def __init__(self, master=None):
Frame.__init__(self, master)
self.grid(row=0, column=0, sticky='news')

DateNow = datetime.datetime.now()
month = int(DateNow.month)
year = int(DateNow.year)
self.createDaysOfWeekLabels()
month_name = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
# Create frames and button controls for previous, current and next month.
self.frameList = # List that contains the frame objects.
self.buttonList = # List that contains the button objects.
amonth = month - 1
for i in range(3):
if amonth < 0:
amonth = 11
year -= 1
elif amonth == 12:
amonth = 1
year += 1

mFrame = Frame(self)
self.createMonth(mFrame, amonth, year)
self.frameList.append(mFrame)
mButton = Button(self, text=month_name[amonth-1])
mButton['command'] = lambda f=mFrame, b=mButton: self.showMonth(f, b)
mButton.grid(row=0, column=i)
# Grid each frame
mFrame.grid(row=2, column=0, columnspan=7, sticky='news')
if (i == 1):
mButton['relief'] = 'flat'
else:
# Remove all but the ith frame. More efficient to remove than forget and configuration is remembered.
mFrame.grid_remove()
self.buttonList.append(mButton)
amonth += 1

# Create year widget at top left of top frame
label = Label(self, text=year)#displaying year
label.grid(row=0, column=6)


def createDaysOfWeekLabels(self):
days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
for i in range(7):
label = Label(self, text=days[i])
label.grid(row = 1, column = i)

def showMonth(self, mFrame, mButton):
# Display all buttons normally
for button in self.buttonList:
button['relief'] = 'raised'

# Set this month's button relief to flat
mButton['relief'] = 'flat'

# Hide all frames
for frame in self.frameList:
frame.grid_remove()

mFrame.grid()

def createMonth(self, mFrame, month, year):
weekday, numDays = monthrange(year, month)
week = 0
for i in range(1, numDays + 1):
button = Button(mFrame, text = str(i), width=3)
button.grid(row = week, column = weekday)

weekday += 1

if weekday > 6:
week += 1
weekday = 0

mainWindow = Tk()
obj = Application(mainWindow)
mainWindow.mainloop()


then I tried to do something similar but using a dictionary whose key is a coordinate tuple and the value is the button(which has a frame as a parent), like this:



coords = {(0, 0):ttk.Button(self.frame_p1g), (0, 1): ttk.Button(self.frame_p1g)}


I just used this same dict for my grid, and this code down here, and it works perfectly:



x = 2
for i in coords.values():
i.grid(row=x, column=2)
x += 1


Image of the result



But as soon as I use a simple function to generate a grid automatically, and then place it in the grid, it doesn't work:



def make(width, height, element):
grid = {}
for y in range(height):
for x in range(width):
print ("X: " + str(x))
print ("Y: " + str(y))
grid[x, y] = element
return grid


Image with result



I tried to find the cause, but the only thing I could find was that the function seems to create exact same buttons, and somehow when I try to place them, every button gets the same row and column config:



Dict print from working dict



Dict print from bugged list



And this is the code that places each button(just pretty similar to the other, just using the lengh of the dict to know where to place them)



    self.p1g = make(int(self.size[0]), int(self.size[1]), ttk.Button(self.frame_p1g))
print(self.p1g)
x = 2
y = 2
for butt in self.p1g.values():
butt.grid(row=y, column=x)
x += 1
if x > (list(self.p1g.keys())[-1][0]):
x = 2
y += 1


The question: How can I make it work with a dict?(I really need those coordinates to reference the buttons)







python-3.x dictionary tkinter ttk






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 21 '18 at 3:23









Carlos HidalgoCarlos Hidalgo

611




611








  • 2





    I recommend by starting with a single function that creates the grid and does nothing else. You've posted too much extra code that isn't relevant to the question being asked, which makes it hard to read and understand. It's important to narrow the code down to the smallest Minimal, Complete, and Verifiable example possible.

    – Bryan Oakley
    Nov 21 '18 at 3:37













  • It references to the same object because make function operates on only one element, hence one element has one set of coordinates at a time. Is there a problem with creating buttons inside of the make instead of passing one? Looks like someone's inattention or I missed something.

    – CommonSense
    Nov 21 '18 at 8:03














  • 2





    I recommend by starting with a single function that creates the grid and does nothing else. You've posted too much extra code that isn't relevant to the question being asked, which makes it hard to read and understand. It's important to narrow the code down to the smallest Minimal, Complete, and Verifiable example possible.

    – Bryan Oakley
    Nov 21 '18 at 3:37













  • It references to the same object because make function operates on only one element, hence one element has one set of coordinates at a time. Is there a problem with creating buttons inside of the make instead of passing one? Looks like someone's inattention or I missed something.

    – CommonSense
    Nov 21 '18 at 8:03








2




2





I recommend by starting with a single function that creates the grid and does nothing else. You've posted too much extra code that isn't relevant to the question being asked, which makes it hard to read and understand. It's important to narrow the code down to the smallest Minimal, Complete, and Verifiable example possible.

– Bryan Oakley
Nov 21 '18 at 3:37







I recommend by starting with a single function that creates the grid and does nothing else. You've posted too much extra code that isn't relevant to the question being asked, which makes it hard to read and understand. It's important to narrow the code down to the smallest Minimal, Complete, and Verifiable example possible.

– Bryan Oakley
Nov 21 '18 at 3:37















It references to the same object because make function operates on only one element, hence one element has one set of coordinates at a time. Is there a problem with creating buttons inside of the make instead of passing one? Looks like someone's inattention or I missed something.

– CommonSense
Nov 21 '18 at 8:03





It references to the same object because make function operates on only one element, hence one element has one set of coordinates at a time. Is there a problem with creating buttons inside of the make instead of passing one? Looks like someone's inattention or I missed something.

– CommonSense
Nov 21 '18 at 8:03












0






active

oldest

votes











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53404821%2fttk-buttons-in-python-dict-reference-to-the-same-object-generation-problem%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























0






active

oldest

votes








0






active

oldest

votes









active

oldest

votes






active

oldest

votes
















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53404821%2fttk-buttons-in-python-dict-reference-to-the-same-object-generation-problem%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







這個網誌中的熱門文章

Xamarin.form Move up view when keyboard appear

Post-Redirect-Get with Spring WebFlux and Thymeleaf

Anylogic : not able to use stopDelay()