1

I'm trying to create new entry boxes when the "ADD entry" is used for my program. I do realize that the 'pack codes' works when I run it individually, but when I combine with existing program which is in grid(), the window is not showing when I run my program.

I also understand that we should not to use both .pack() when I have other things using .grid() in the same program. Hence, my question is, how do I create new entry boxes in grid.

I have tried finding elsewhere but they all suggested pack. For instance: I have looked here here, etc etc, to name a few; but couldn't find anything similar to mine. I would like to add entry boxes below the current entry boxes which is at row 3.

I'm kind of new to Python; (am using Python 2.7 and tkinter module in this program. Thank you very much for the help! My simplified error codes are as follows:

from Tkinter import *
import tkFileDialog
import tkMessageBox
import Tkinter
import os

class Window:

 def __init__(self, master):

    self.filename3=""
    csvfile=Label(root, text="NUMBERS").grid(row=3, column=0)
    bar=Entry(master).grid(row=3, column=3)
    self.entryText3 = StringVar()
    self.bar = Entry(root, textvariable=self.entryText3).grid(row=3, column=3)

    #BUTTONS
    self.cbutton= Button(root, text="OK", command=self.process_csv)
    self.cbutton.grid(row=15, column=6, sticky = W + E)

####PROBLEM FROM HERE#####
    all_entries = []
    addboxButton = Button(root, text='ADD', fg="BLUE", command=self.addBox)
    addboxButton.pack()

#I have also tried replacing the last 2 lines with the following 2 lines instead but to no avail:     
#self.addboxButton = Button(root, text='ADD THA-ID', fg="BLUE", command=self.addBox)
#self.addboxButton.grid(row=3, column=6)

    frame_for_boxes = Frame(root)
    frame_for_boxes.pack()

 def addBox(self):
    print "ADD"
    next_row = len(all_entries)
    lab = Label(frame_for_boxes, text=str(next_row+1))
    lab.grid(row=next_row, column=0)
    ent = Entry(frame_for_boxes)
    ent.grid(row=next_row, column=0)
    all_entries.append( ent )

 def process_csv(self):
    #own program here
    print "program"
root = Tk()
window=Window(root)
root.mainloop()
Community
  • 1
  • 1
Sandy
  • 45
  • 1
  • 8
  • 1
    _"I also understand that we should not to use both .pack() when I have other things using .grid() in the same program."_ - that is not a correct statement. You can use both `grid` and `pack` in the same _program_, just not for two or more widgets that share the same _parent_. – Bryan Oakley Mar 28 '17 at 11:12

2 Answers2

1

There are few issues with your program other than the one you stated:

  1. Inside the initializer (__init__()) you attached the widgets to root which is not defined within the scope of your Window class. The reasonable way to fix this issue is when you use an instance of Tk(), id est root id est master in Window class, make it as an instance variable. This means the first thing you have to do in the inititializer is this : self.master = master. This will result in you having to replace all root occurrences within __init__() by self.master

  2. The second issue to fix is the one you specified in your question's title: you can not mix the grid() and pack() layout managers for the same widget container. You have to decide which one. Since you placed most of the widgets using grid(), I suggest you to get rid of pack(). This means:

    • addboxButton.pack() becomes, for example, addboxButton.grid(row=0, column=1)
    • frame_for_boxes.pack() becomes, for example, frame_for_boxes.grid(row=0, column=0)
  3. The previous list item fixes the problem but it will make you discover other issues within your program which are related:

    • NameError: global name 'all_entries' is not defined
    • NameError: global name 'frame_for_boxes' is not defined

    This is because those widget variables are not reachable within the scope of addBox() function. To resolve this issue, you have to make those 2 elements as instance variables. This means:

    • all_entries = [] becomes self.all_entries = []
    • frame_for_boxes = Frame(root) becomes self.frame_for_boxes = Frame(self.master) (remember we replaced root by self.master in 1.)

    The consequence of this error fixing is that you have to use all over inside your program:

    • self.all_entries instead all_entries
    • self.frame_for_boxes instead of frame_for_boxes
  4. For scalability reasons, I think you will have at least to make the rest of widgets as instance variables (i.d. prefix them with the self keyword)

  5. As your real project is more complicated than what you show in this MCVE, I encourage you to adopt the SaYa idiom when creating and placing widget elements. This means you will need to replace:

      csvfile=Label(root, text="NUMBERS").grid(row=3, column=0)
    

    by

      self.csvfile = Label(self.master, text="NUMBERS")
      self.csvfile.grid(row=3, column=0)
    

    To avoid unexpected bugs in your program, you must do the same for the remaining widgets you declared in the inititialzer.

  6. There are also other things I would like to mention, but most of them are available on PEP8

Billal Begueradj
  • 20,717
  • 43
  • 112
  • 130
0

What you have to do it to create a command which creates the entries and stores the new entries inside of a variable. In my case, I use Entry_i and store in Entries but you can use self.Entries to make communication easier. (python 3.5)

def Make_Entry(self, root, Entries, x, y):

    Entry_i = Entry(root, bd = 5)
    Entry_i.grid(row = x, column = y, sticky = W+E+N+S)
    Entries.append(Entry_i)
    return(Entries, x+1, y+1)
Stijn Van Daele
  • 285
  • 1
  • 14