0
window = Tk() #create app window



#custom message box function 
def answerMessagebox(returnValue, toplevel, functionName=""):
    global answer
    answer = returnValue

    print("The answer variable is (inside answerMessagebox function): ", answer)

    if functionName: #if there is a command do this
        functionName()

    toplevel.destroy() #close messagebox

def messageboxYesNo(title, text, functionName=""):

    toplevel = Toplevel(window)
 
    toplevel.title(title)
    
    l1=Label(toplevel, image=iconQuestion)
    l1.grid(row=0, column=0, pady=(7, 0), padx=(10, 30), sticky="e")

    l2=Label(toplevel,text=text)
    l2.grid(row=0, column=1, columnspan=3, pady=(7, 10), sticky="w")
 
    b1=Button(toplevel,text="Yes",command=lambda: answerMessagebox(True, toplevel, functionName=functionName),width = 10)
    b1.grid(row=1, column=1, padx=(2, 35), sticky="e")

    b2=Button(toplevel,text="No",command= lambda: answerMessagebox(False, toplevel), width = 10)
    b2.grid(row=1, column=2, padx=(2, 35), sticky="e")



def close_window():
    driver.quit() 
    window.destroy()
    exit() 

exitButton = Button(window, text="Exit", command=lambda: messageboxYesNo("QUIT", "Are you sure you want to Quit?", functionName=close_window), font=breadtextFont, bg=button_color, fg=button_text_color) #add a exit button
exitButton.pack(side="top", anchor=NE, padx=15, pady=10)

window.mainloop()

The print statement inside answerMessagebox prints out correctly False if I press No-button and True if I press Yes-button. I want to use that answer inside another function and do logic based on the answer.

def foo():
    global answer
    answer = ""
    messageboxYesNo("Submit report", "Are you sure you want to submit?") #expect global variable to change to True if press Yes-button. But it actually prints out nothing. 

    if answer:
       #do something 

Inside the foo()function the global variable answerdoes not change after I run the messageboxYesNo function and therefore the if answer: statements is not running.

Why is the global variable not changing? I guess it is because foo() continues and is not waiting for messageboxYesNo function to finish. How can I solve this issue?

I use a global variable because the command= in tkinter cannot return anything from a function.

AppCreator
  • 241
  • 1
  • 2
  • 11
  • When you set `command=` to some function, the function will get called when the Button is pressed. All your code is doing is setting that up, which is why the `print()` at the end of the function doesn't print what you're expecting (i.e. the function hasn't executed and changed the value of the global variable named `answer` at that point). – martineau Jan 31 '22 at 10:39
  • You do not provide reproducible code. Also i strongly suggest to remove complexity, e.g. by merging both things into one function without having to define global variables – mnikley Jan 31 '22 at 10:51
  • I have updated the question to reflect what I really mean. – AppCreator Jan 31 '22 at 11:35

2 Answers2

1

Your code does not show when foo() is being executed, however at the beginning you are already overriding the value of answer with an empty string, which later evaluates to false:

def foo():
    global answer
    answer = "" # Remove this line

There are many issues with this usage of global variables, and an OOP refactor would be the best approach to address it. However, a quick solution for this specific problem would be passing the result from answerMessagebox to the callback:

def answerMessagebox(returnValue, toplevel, functionName=""):
    answer = returnValue
    print("The answer variable is (inside answerMessagebox function): ", answer)

    if functionName:
        functionName(answer)
    # ...

def foo(answer):
    # ...
A. Rodas
  • 20,171
  • 8
  • 62
  • 72
  • I'm fairly new to OOP. How can I refactor this to OOP so that I'm able to call a tkinter command and return a value from the command? (e.g. return True/False in a variable depending whether Yes-button was clicked or not) – AppCreator Jan 31 '22 at 12:53
  • It requires a major rewrite that goes beyond the scope of this question, but you can read more about it [here](https://stackoverflow.com/q/17466561/) – A. Rodas Jan 31 '22 at 14:26
0

The last print statement is executed soon after you press the Exit button. It simply creates the UI for the labels and the Yes/No buttons, prints the last statement and exists the function.

When you press the Yes/No buttons, it executes the answerMessagebox function. If you want something to execute after the changes to answer have been made, either add it to the end of the answerMessagebox function or (maybe in the case that it doesn't make sense to have it on the same function) execute a separate function at the end of the function:

def answerMessagebox(returnValue, toplevel, functionName=""):
    answer = returnValue
    
    # The logic you've written already
    
    toplevel.destroy() #close messagebox
    
    everythingAfterYesNoPress(answer)


def everythingAfterYesNoPress(answer = ""):
    print("This is answer variable after messageboxYesNo function", answer)

Edit: I think what you're looking for is wait_window.

Initialize toplevel inside the foo function before the messageboxYesNo function and pass it as a parameter to the function instead of defining it inside (of course, you'd have to change the messageboxYesNo function a bit). Then add the wait_window line after executing the function:

toplevel = Toplevel(window)
messageboxYesNo(toplevel, "Submit report", "Are you sure you want to submit?")
window.wait_window(toplevel)
Dilith Jayakody
  • 136
  • 1
  • 5