Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I add a lot of Buttons to the tkinter Frame efficiently?

I want to add 10 buttons to Tkinter, named One to Ten. I basically just used the brute force method, adding each button as I went, in the init function of my application's class. It works, but I want to minimize the code used, to be more efficient, such as using a data structure to hold all the buttons.

I was thinking of using a buttonBox to hold all the buttons in, but I was not sure if I could manipulate the placement via grid() to place the buttons how I wanted.

self.one = Button(frame, text="One", command=self.callback)
self.one.grid(sticky=W+E+N+S, padx=1, pady=1)

self.two = Button(frame, text="Two", command=self.callback)
self.two.grid(sticky=W+E+N+S, row=0, column=1, padx=1, pady=1)

self.three = Button(frame, text="Three", command=self.callback)
self.three.grid(sticky=W+E+N+S, row=0, column=2, padx=1, pady=1)

# ...

self.ten = Button(frame, text="Ten", command=self.callback)
self.ten.grid(sticky=W+E+N+S, row=1, column=4, padx=1, pady=1)

Can anyone show me a way to make this more efficient, such as a data structure?

like image 247
thatbennyguy Avatar asked Aug 21 '11 10:08

thatbennyguy


People also ask

Can you give a button multiple commands Tkinter?

We can perform a certain action with the help of a Button that encapsulates the function and the objects. However, there might be cases when we want to perform multiple operations with a single button. This can be achieved by defining the lambda functions which target multiple events or callback in the application.

How do I position buttons in Tkinter?

The button in the tkinter module can be placed or move to any position in two ways: By using the place() method. And by using the pack() method.

Can you nest frames in Tkinter?

The frame is a widget or container which used to handle the tkinter GUI. Frist, we will create the main frame or parent frame, inside it, we have created nested frames. When we need to devided the window more than two or three parts then we will use the concept of Frame.

Can I put button on canvas Tkinter?

You can use canvas to draw different shapes, arcs, and objects to animate within the canvas. To create a button on a Tkinter Canvas, simply pass the parent as the canvas in place of a parent in the Button constructor.


2 Answers

Instead of naming the buttons self.one, self.two, etc., it would be more convenient to refer to them by indexing a list, such as self.button.

If the buttons do different things, then you just have to explicitly associate buttons with callbacks. For example:

name_callbacks=(('One',self.callback_one),
                ('Two',self.callback_two),
                ...,
                ('Ten',self.callback_ten))
self.button=[]
for i,(name,callback) in enumerate(name_callbacks):
    self.button.append(Button(frame, text=name, command=callback))
    row,col=divmod(i,5)
    self.button[i].grid(sticky=W+E+N+S, row=row, column=col, padx=1, pady=1)

If the buttons all do similar things, then one callback may suffice to service them all. Since the callback itself can't take arguments, you can setup a callback factory to pass the arguments in through a closure:

def callback(self,i): # This is the callback factory. Calling it returns a function.
    def _callback():
        print(i) # i tells you which button has been pressed.
    return _callback

def __init__(self):
    names=('One','Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten')
    self.button=[]
    for i,name in enumerate(names):
        self.button.append(Button(frame, text=name, command=self.callback(i+1)))
        row,col=divmod(i,5)
        self.button[i].grid(sticky=W+E+N+S, row=row, column=col, padx=1, pady=1)
like image 82
unutbu Avatar answered Sep 19 '22 04:09

unutbu


You could put all the buttons properties in a dict, and then loop on it to create your buttons, here is an example:

buttons = {
    'one': {'sticky': W+E+N+S, 'padx': 1, 'pady': 1},
    'two': {'sticky': W+E+N+S, 'row': 0, 'column': 1, 'padx': 1, 'pady': 1},
    'three': {'sticky': W+E+N+S, 'row': 0, 'column': 2, 'padx': 1, 'pady': 1}
}
for b in buttons:
    button = Button(frame, text=b.title(), command=self.callback)
    button.grid(**buttons[b])
    setattr(self, b, button)

This would also allow you to easily add new buttons if needed.

like image 34
mdeous Avatar answered Sep 19 '22 04:09

mdeous