Search code examples
pythontkintertkinter-button

Resuming code execution after popup in TKinter


In download_images() I want to prompt the user if the last updated data for the data is correct and if they want to proceed. To do this, I am using a popup window. However, after the user selects 'yes' the code in download_images() is never resumed.

def download_images(self, pat, name):
        tableau_config = {
            "tableau_prod": {
                "server": "https://tableau.****.com",
                "api_version": "3.19",
                "personal_access_token_name": name,
                "personal_access_token_secret": pat,
                "site_name": "Consolidated",
                "site_url": "Consolidated",
            }
        }

        connection = TableauServerConnection(
            config_json=tableau_config, env="tableau_prod", ssl_verify=False
        )
        connection.sign_in()

        wb = connection.query_workbook(
            workbook_id="3eed5185"
        )

        # Cred check
        if wb.status_code != 200:
            self.okPopup("Invalid Credentials, try again.")

        workbook_views = json.loads(wb.content.decode("utf-8").replace("'", '"'))[
            "workbook"
        ]["views"]["view"]

        for rows in workbook_views:
            if rows["name"] == "Senior Management (CIO)":
                self.yesNoPopup(
                    f"The data was last updated on {rows['updatedAt'][:10]}. Would you like to proceed?"
                )
                if not self.yesNoValue:
                    break

        # ADDITIONAL CODE ***
        # ADDITIONAL CODE ***
        # ADDITIONAL CODE ***
class GuiGo(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.parent = parent
        self.initialize_user_interface()

    def initialize_user_interface(self):
        self.parent.geometry("500x120")
        self.parent.title("CIO Monthly Report Automation")

        self.a1 = tk.Label(self.parent, text="Enter Tableau Token Name:")
        self.a1.grid(row=0, column=0)
        self.E1 = tk.Entry(self.parent)
        self.E1.grid(row=0, column=1)

        self.a2 = tk.Label(self.parent, text="Enter Tableau Token Value:")
        self.a2.grid(row=1, column=0)
        self.E2 = tk.Entry(self.parent)
        self.E2.grid(row=1, column=1)

        self.a3 = tk.Label(self.parent, text="Enter Path for file creation:")
        self.a3.grid(row=2, column=0)
        self.E3 = tk.Entry(self.parent)
        self.E3.grid(row=2, column=1)
        btnFind = tk.Button(
            self.parent, text="Browse Folder", command=self.getFolderPath
        )
        btnFind.grid(row=2, column=2)

        c = tk.Button(self.parent, text="run", command=self.doStuff)
        c.grid(row=4, column=1)

    def doStuff(self):
        self.download_images(self.E2.get(), self.E1.get())
        if self.yesNoValue:
            for cio in self.cio_list:
                self.crop_images()
                self.populate_presentation(
                    tableau_cio_filter_value=parse.quote(cio),
                    filename=self.cio_list[cio],
                    path=self.E3.get(),
                )
        self.completionPopup("Generation Complete!")

    def get_button(self, t):
        self.yesNoValue = t

    def yesNoPopup(self, msg):
        popup = tk.Toplevel()
        popup.wm_title("!")
        label = tk.Label(popup, text=msg)
        label.pack(side="top", fill="x")
        B1 = tk.Button(
            popup, text="Yes", command=lambda: [popup.destroy(), self.get_button(True)]
        B1.pack()
        B2 = tk.Button(
            popup, text="No", command=lambda: [popup.destroy(), self.get_button(False)]
        )
        B2.pack()
        popup.mainloop()


if __name__ == "__main__":
    root = tk.Tk()
    run = GuiGo(root)
    root.mainloop()

I believe this issue has something to do with how the root.mainloop and popup.mainloop interact. I've tried closing the main window, and the code will resume executing, but then, I don't have my main window anymore. I've tried popup.quit() instead of popup.destroy() and this also works but leaves the popup window open for the rest of the execution.


Solution

  • You shouldn't be calling mainloop a second time. As a general rule of thumb you should call it exactly once during the life of the program.

    Instead, use the wait_window method which will not return until the window has been destroyed.

        def yesNoPopup(self, msg):
            popup = tk.Toplevel()
            ...
            popup.wait_window()