0

When I define the following function, all the other widgets that I define inside the function are appearing and are functional. I can modify the entries and get the values from them.

`

def frame(self):
    new_frm = tk.Frame(self.window,  width=200, 
        height=200, bg="white"
    ).place(x=self.x0, y=0)
    self.frame_list.append(new_frm)
    lbl = tk.Label(master=new_frm, relief=tk.RIDGE, 
               text=param_name, fg = "white", bg="black",   
               anchor="w", font=("Arial", 20)
   )
    lbl.place(x = self.x0, y = 0)
    self.x0 += 205

`

enter image description here

But if I change the code to below, only the frame appears and not the widgets. But, the widgets are still as functional as the first case. I wonder why this happens and how I can fix it.

`

def frame(self):
    new_frm = tk.Frame(self.window,  
          width=200, height=200, bg="white"
    )
    new_frm.place(x=self.x0, y=0)
    new_frm = tk.Frame(self.window,  width=200, height=200, bg=color)
    self.frame_list.append(new_frm)
    lbl = tk.Label(master=new_frm, relief=tk.RIDGE, 
               text=param_name, fg = "white", bg="black",   
               anchor="w", font=("Arial", 20)
   )
    lbl.place(x = self.x0, y = 0)
    self.x0 += 205

`

enter image description here

I want to put the new_frm into frame_list so I can get access to all frames later. Of course, when I use new_frm = tk.Frame(self.window, width=200,height=200, bg="white").place(x=self.x0, y=0) , the new_frm become a Nonetype and it doesn't work.

Update:

The solution mentioned by @Kartikeya is to use .grid() for widgets inside the frame. Therefore, the code must be written this way: `

def frame(self):
    new_frm = tk.Frame(self.window,  
          width=200, height=200, bg="white"
    )
    new_frm.place(x=self.x0, y=0)
    new_frm = tk.Frame(self.window,  width=200, height=200, bg=color)
    self.frame_list.append(new_frm)
    lbl = tk.Label(master=new_frm, relief=tk.RIDGE, 
               text=param_name, fg = "white", bg="black",   
               anchor="w", font=("Arial", 20)
   )
    lbl.grid(row = 0, column = 0)
    self.x0 += 205

`

  • How do you create *the other widgets*? Note that `new_frm` is None in first example. – acw1668 Jun 29 '21 at 04:24
  • If you are using `.pack()` or `.grid()` with those child widgets, then this problems occurs because you are using `.place()` with the frame in 2nd case. You can get an idea from [this answer](https://stackoverflow.com/a/29102873/14465779) – Kartikeya Jun 29 '21 at 05:47
  • For your case, a quick-fix can be to do `place()` with all the child widgets of frame, and your problem will be solved – Kartikeya Jun 29 '21 at 05:51
  • @acw1668 Yes. That is why I needed it to be in a separate line so I can make a list of frames only. – Arash Fahim Jun 29 '21 at 13:42
  • @Kartikeya Fair enough. It completely make sense the the parent covers all children. I should have thought of it. But still it is a mystery that this only occurs inside a function. When I take it out of the function, frame does not cover the children widgets. I didn't quite get your suggested quick fix. Can you please clarify? – Arash Fahim Jun 29 '21 at 13:45
  • I cannot reproduce the problem, so better provide [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – acw1668 Jun 29 '21 at 14:13
  • No, please don't mix more than one geometry manager, like you used both `.place()` and `.grid()` . What I meant to say was, 1st- use either `.place()`, or `.pack()`, or `grid()` , any one of them. 2nd- It is usually not a good idea to use `.place()` for ordinary window and dialog layouts because then there is simply too much work to get things working as they should. Use the `pack()` or `grid()` managers for such purposes. – Kartikeya Jun 30 '21 at 01:33
  • Now, to address your query, I'm just commenting and not answering since there is no [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example), 1st- make sure the `width` and `height` of frame (i.e. 200 and 200) is big enough for contents to be visible. 2nd- In `place()` method, you can use `in_` option to put one widget inside another. Consider using it. – Kartikeya Jun 30 '21 at 01:37

1 Answers1

0

It is because you have created new_frm twice in second/third example:

def frame(self):
    # first "new_frm"
    new_frm = tk.Frame(self.window,  
          width=200, height=200, bg="white"
    )
    new_frm.place(x=self.x0, y=0)
    # second "new_frm" which ovrrides the above one
    # and it is invisible because it is not .pack()/grid()/place()
    new_frm = tk.Frame(self.window,  width=200, height=200, bg=color)
    self.frame_list.append(new_frm)
    # label are put in the invisible "new_frm", so it is not visible as well
    lbl = tk.Label(master=new_frm, relief=tk.RIDGE, 
               text=param_name, fg = "white", bg="black",   
               anchor="w", font=("Arial", 20)
    )
    lbl.place(x = self.x0, y = 0)
    self.x0 += 205

Remove the second creation of new_frm:

def frame(self):
    new_frm = tk.Frame(self.window,
          width=200, height=200, bg="white"
    )
    new_frm.place(x=self.x0, y=0)
    # below line should not be called
    #new_frm = tk.Frame(self.window,  width=200, height=200, bg=color)
    self.frame_list.append(new_frm)
    lbl = tk.Label(master=new_frm, relief=tk.RIDGE,
               text=param_name, fg = "white", bg="black",
               anchor="w", font=("Arial", 20)
    )
    lbl.place(x = self.x0, y = 0)
    self.x0 += 205
acw1668
  • 40,144
  • 5
  • 22
  • 34