22

I want to run multiple functions when I click a button. For example I want my button to look like

self.testButton = Button(self, text = "test", 
                         command = func1(), command = func2())

when I execute this statement I get an error because I cannot allocate something to an argument twice. How can I make command execute multiple functions.

nbro
  • 15,395
  • 32
  • 113
  • 196
user1876508
  • 12,864
  • 21
  • 68
  • 105

11 Answers11

60

You can simply use lambda like this:

self.testButton = Button(self, text=" test", command=lambda:[funct1(),funct2()])
pradepghr
  • 634
  • 5
  • 6
31

You could create a generic function for combining functions, it might look something like this:

def combine_funcs(*funcs):
    def combined_func(*args, **kwargs):
        for f in funcs:
            f(*args, **kwargs)
    return combined_func

Then you could create your button like this:

self.testButton = Button(self, text = "test", 
                         command = combine_funcs(func1, func2))
Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
  • How to do this if this `combine_funcs` is method in a class? If I write `def combine_funcs(self, *funcs):` I get an error `TypeError: my_first_func() takes 1 positional argument but 2 were given – Hrvoje T May 30 '18 at 11:42
18
def func1(evt=None):
    do_something1()
    do_something2()
    ...

self.testButton = Button(self, text = "test", 
                         command = func1)

maybe?

I guess maybe you could do something like

self.testButton = Button(self, text = "test", 
                         command = lambda x:func1() & func2())

but that is really gross ...

Joran Beasley
  • 110,522
  • 12
  • 160
  • 179
  • 1
    Defining a function to do what you want is probably the best solution. Putting some of the logic within the button itself strikes me as icky, and a potential maintenance problem later. – PeterBB Dec 13 '12 at 17:55
5

You can use the lambda for this:

self.testButton = Button(self, text = "test", lambda: [f() for f in [func1, funct2]])
blkpws
  • 151
  • 1
  • 3
5

Button(self, text="text", command=func_1()and func_2)

adiga
  • 34,372
  • 9
  • 61
  • 83
chibbbb
  • 51
  • 1
  • 1
  • 9
    While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value. – adiga Nov 30 '17 at 10:46
4

I think the best way to run multiple functions by use lambda.

here an example:

button1 = Button(window,text="Run", command = lambda:[fun1(),fun2(),fun3()])
1

I've found also this, which works for me. In a situation like...

b1 = Button(master, text='FirstC', command=firstCommand)
b1.pack(side=LEFT, padx=5, pady=15)

b2 = Button(master, text='SecondC', command=secondCommand)
b2.pack(side=LEFT, padx=5, pady=10)

master.mainloop()

... you can do...

b1 = Button(master, command=firstCommand)
b1 = Button(master, text='SecondC', command=secondCommand)
b1.pack(side=LEFT, padx=5, pady=15)

master.mainloop()

What I did was just renaming the second variable b2 the same as the first b1 and deleting, in the solution, the first button text (so only the second is visible and will act as a single one).

I also tried the function solution but for an obscure reason it don't work for me.

lucians
  • 2,239
  • 5
  • 36
  • 64
1

this is a short example : while pressing the next button it will execute 2 functions in 1 command option

    from tkinter import *
    window=Tk()
    v=StringVar()
    def create_window():
           next_window=Tk()
           next_window.mainloop()

    def To_the_nextwindow():
        v.set("next window")
        create_window()
   label=Label(window,textvariable=v)
   NextButton=Button(window,text="Next",command=To_the_nextwindow)

   label.pack()
   NextButton.pack()
   window.mainloop()
0

check this out, I have tried this method as,I was facing the same problem. This worked for me.

def all():
    func1():
        opeartion
    funct2():
        opeartion
    for i in range(1):
        func1()
        func2()

self.testButton = Button(self, text = "test", command = all)
0

I was looking for different solution. One button doing two functions on two different clicks. Example START button - after click changes text to STOP and starts function. After second click stop function and changes text to START again. Tried this and it works. I do not know if it is ok or elegant or does not break any python rules (I am a lousy programmer :-) but it works.

from tkinter import *

root=Tk()

def start_proc():
    print('Start')
    myButton.configure(text='STOP',command=stop_proc)

def stop_proc():
    print('stop')
    myButton.configure(text='START',command=start_proc)

myButton=Button(root,text='START' ,command=start_proc)
myButton.pack(pady=20)

root.mainloop()
Fa J
  • 1
  • 2
  • Hi, and thanks for contributing. This is surely useful, but it answers a different question, not the OP's. If you feel like sharing your knowledge, consider posting your own question; you are then free to post an answer to your own question, too. See: https://stackoverflow.com/help/self-answer – Daniil Fajnberg Aug 29 '22 at 18:31
  • If you have a new question, please ask it by clicking the [Ask Question](https://stackoverflow.com/questions/ask) button. Include a link to this question if it helps provide context. - [From Review](/review/late-answers/32570349) – Willie Cheng Aug 31 '22 at 02:26
0

You can solve this issue by simply adding your second function at the end of the first function, but only passing the first function as a command. This will trigger both functions but following a sequence. I like this approach as it allows for a greater flexibility since you can add custom logic to be followed before the second function is called.
PS: In your code you should avoid adding ( ) when binding your function with the command arg as you did.

def func1():
    pass
    #code to execute before func2() is called

    def func2():
        pass
        #code of func2()

    pass
    #code after func2() is executed