5

How do i make the button to add two box (side by side) below when it is being clicked as the user decided to put more input?

def addBox():
    labelframe = Tkinter.Frame()
    labelframe.bind("<Add Input>", callback)
    labelframe.pack()

labelframe = Tkinter.Frame()

labelFrom = Tkinter.Label(labelframe, text= "from")
labelFrom.grid(column=1, row=0)
e = Tkinter.Entry(labelframe)
e.grid(column=1, row=1)

labelTo = Tkinter.Label(labelframe, text= "to")
labelTo.grid(column=2, row=0)
e2 = Tkinter.Entry(labelframe)
e2.grid(column=2, row=1)

labelframe.pack()

addboxButton = Button( root,text='<Add Time Input>', fg="Red",command="addBox")
addboxButton.pack(side=Tkinter.TOP)
user3817491
  • 117
  • 1
  • 3
  • 13
  • Did you indent your function properly?? `def addBox()` should have the codes in indent – Riq Jul 18 '14 at 21:03
  • 1
    You should not indent the entire code!!! Now all of your code will run when `def addBox()` will be called. Indent in Python works like curly braces `{ }` in javascript, PHP. So basically indent only that part of the code which you want it to be inside the function. – Riq Jul 18 '14 at 21:11
  • 2
    You **shouldn't** use **`pack()`** and **`grid()`** together. – Riq Jul 18 '14 at 21:15
  • 3
    Use function name without quotation marks `command=addBox` – furas Jul 18 '14 at 21:20

2 Answers2

4

This is example how to add Entry.

Probably you get problem because you use quotation marks in command=addBox

Because you will have to get values from entries you have to remeber them on list.
I add button which print text from entries.

from Tkinter import *

#------------------------------------

def addBox():
    print "ADD"

    ent = Entry(root)
    ent.pack()

    all_entries.append( ent )

#------------------------------------

def showEntries():

    for number, ent in enumerate(all_entries):
        print number, ent.get()

#------------------------------------

all_entries = []

root = Tk()

showButton = Button(root, text='Show all text', command=showEntries)
showButton.pack()

addboxButton = Button(root, text='<Add Time Input>', fg="Red", command=addBox)
addboxButton.pack()

root.mainloop()

#------------------------------------

EDIT:

Example with boxes side by side.

I use new frame to keep entries side by side using grid().
This way I don't mix grid() with pack() in main window/frame.

I use len(all_entries) to get number of next free column.

from Tkinter import *

#------------------------------------

def addBox():
    print "ADD"

    # I use len(all_entries) to get nuber of next free column
    next_column = len(all_entries)

    # add label in first row 
    lab = Label(frame_for_boxes, text=str(next_column+1))
    lab.grid(row=0, column=next_column)

    # add entry in second row
    ent = Entry(frame_for_boxes)
    ent.grid(row=1, column=next_column)

    all_entries.append( ent )

#------------------------------------

def showEntries():

    for number, ent in enumerate(all_entries):
        print number, ent.get()

#------------------------------------

all_entries = []

root = Tk()

showButton = Button(root, text='Show all text', command=showEntries)
showButton.pack()

addboxButton = Button(root, text='<Add Time Input>', fg="Red", command=addBox)
addboxButton.pack()

frame_for_boxes = Frame(root)
frame_for_boxes.pack()

root.mainloop()

#------------------------------------

enter image description here


EDIT:

Another example:

from Tkinter import *

#------------------------------------

def addBox():
    print "ADD"

    frame = Frame(root)
    frame.pack()

    Label(frame, text='From').grid(row=0, column=0)

    ent1 = Entry(frame)
    ent1.grid(row=1, column=0)

    Label(frame, text='To').grid(row=0, column=1)

    ent2 = Entry(frame)
    ent2.grid(row=1, column=1)

    all_entries.append( (ent1, ent2) )

#------------------------------------

def showEntries():

    for number, (ent1, ent2) in enumerate(all_entries):
        print number, ent1.get(), ent2.get()

#------------------------------------

all_entries = []

root = Tk()

showButton = Button(root, text='Show all text', command=showEntries)
showButton.pack()

addboxButton = Button(root, text='<Add Time Input>', fg="Red", command=addBox)
addboxButton.pack()

root.mainloop()

#------------------------------------

enter image description here

furas
  • 134,197
  • 12
  • 106
  • 148
  • what if i need two box side by side( when button is clicked,it will create two boxes together side by side? i can't seem to make that works – user3817491 Jul 19 '14 at 04:16
  • If you need boxes side by side then use `grid(column=...)`. But don't mix `pack()` and `grid()` in one `Frame`. If you use `pack()` in one frame then create second frame, put it inside first frame and then you can use `grid()` inside second frame. See new example. – furas Jul 19 '14 at 16:15
  • thank you, i can't seem to get the scrollbar working by the way the user needs more inputs it needs to be able to scroll. – user3817491 Jul 19 '14 at 17:18
  • As I know the only method is to use canvas with frame inside to scroll it. See more: http://stackoverflow.com/questions/16188420/python-tkinter-scrollbar-for-frame – furas Jul 19 '14 at 17:54
  • yes i did read on that earlier today,but i can't seem to get it right – user3817491 Jul 19 '14 at 18:00
  • This is the only way - but difficult way. – furas Jul 19 '14 at 18:12
  • Search on internet maybe someone create tkinter widget `Scrolled Frame` – furas Jul 19 '14 at 18:17
  • anyway this can be updated with the latest python version? – excelguy Jan 29 '19 at 02:04
  • @excelguy you have to use `from tkiner` instead of `from Tkinter` (see `t` instead of `T`) and `print()` instead of `print` (you need brackets)- and it works with Python 3. – furas Jan 29 '19 at 02:10
  • @excelguy - yes `tkinter` - I made a typo. – furas Jan 29 '19 at 02:16
0

First of all, the indentation is a whole mess, so I don't know where does the addBox function end ..

Second, I don't think you need a button, I suppose a checkbutton will do the same thing and it's also more common and familiar to users, I once had this problem and I simply created an entry box and put above it a label indicating that it's optional, and as for code, I simply ignored it if it was empty and verified the input if I found any input ..
Howerver, that was for only one entry box, and you probably will need something more complex ..

See this ..

class OptionsView(Frame):
    """Frame for options in main window"""
    def __init__(self, x, y, parent):
        Frame.__init__(self, parent)
        self.x = x
        self.y = y
        self.placed = False
        self.hidden = False
        self.btn = Button(self, text = 'Button attached to the frame ..', command = lambda: print('Button in frame clicked ..')).pack()
    def pack(self):
        self.place(x = self.x, y = self.y)
        self.placed = True
    def toggle_view(self):
        if self.hidden:
            self.pack()
            self.hidden = False
        else:
            self.place_forget()
            self.hidden = True

if __name__ == '__main__':
    def m_frame():
        if val.get() and not options_frame.placed:
            print('Showing Frame ..')
            options_frame.pack()
        else:
            print('Toggling Frame ..')
            options_frame.toggle_view()

    root = Tk()
    root.geometry('300x400+500+600')
    root.title('Testing Hiding Frames ..')
    options_frame = OptionsView(200, 300, root)

    val = BooleanVar(value = False)
    Checkbutton(text = 'View more Options ..', var = val, command = m_frame).place(x=root.winfo_height()/2, y=root.winfo_width()/2)

    try: root.mainloop()
    except e: showerror('Error!', 'It seems there\'s a problem ..', str(e))

Ofcourse you can also modify the length and the x axis of the main window if you want to be more realistic ..

Community
  • 1
  • 1
Amr Ayman
  • 1,129
  • 1
  • 8
  • 24