samuel
samuel

Reputation: 21

Close python Tkinter multiple dialogs

I'm making a GUI in tkinter to do some basic calculus. My problem is that I'm not able to close some dialogs. I want to close them and change visualization by taking the user's choice.My code doesn't wait till the close of the window to do that, wait till the end of the main class. I need help to fix it.

class Plotia(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, *kwargs)
        tk.Tk.wm_title(self, "Plotia")
        s = ttk.Style()
        s.theme_use("clam")

        # Configuration of the window ....
        #....
        #....
        #....
        ## Initial Values ##############################

        self.Number_Graph = 1
        self.path_file = [None for i in range(self.Number_Graph)] # Number of files
        self.columnData = [4 for i in range(self.Number_Graph)] # Number of column of the data
        self.column_x = [0 for i in range(self.Number_Graph)]
        self.column_y = [0 for i in range(self.Number_Graph)]


    def askData(self):
        # I don't understand why ChoiceData don't close. 

        self.graph = ChoiceData(self.Number_Graph, self.columnData)
        # Only when the main window close,  this two lines executes, 
        # and change this two variables. I want that this two lines executes when
        #Choice Data close
        self.column_x[self.graph.selection] = self.graph.data[0]
        self.column_y[self.graph.selection] = self.graph.data[1]







# This is is the Dialog  I can close correctly


class ChoiceData(tk.Toplevel):

    def __init__(self, NumberGraph, NumberData):
        super(ChoiceData, self).__init__()


        ## Initial Values #################################

        self.NumberGraph = NumberGraph
        self.selection = None
        self.numberData = NumberData
        self.data = []

        ########################################################

        # Layout Configure
        #...


    def Select(self):
        self.selection = int(self.BoxList.get())-1
        selectionData = SelectData(self.numberData[self.selection])
        self.data.append(selectionData.xData)
        self.data.append(selectionData.yData)
        self.destroy()



class SelectData(tk.Toplevel):

    def __init__(self, numberData):
        super(SelectData, self).__init__()



        ## Initial Values #################################

        self.xData= None
        self.yData = None
        self.NumberData = numberData

        ########################################################

        # Layout configuration.,,,

    def Update(self):
        self.xData = int(self.xBox.get())-1
        self.yData = int(self.yBox.get())-1
        self.destroy()


if __name__ == '__main__':
    app = Plotia()
    app.geometry("500x500")
    app.mainloop()

EDIT: from tkinter import *

class Quit:
    def __init__(self, root):
        root.destroy()


class ChoiceData:
    def __init__(self,root):
        self.top = Toplevel(root)
        self.label = Label(self.top, text="ChoiceData")
        self.button = Button(self.top, text="Ok", command=self.stuff)
        self.top.protocol("WM_DELETE_WINDOW", lambda: Quit(self.top))
        self.label.pack()
        self.button.pack()

    def stuff(self):
        thing = SelectData(self.top)
        self.top.destroy()
        print("Windows closed")




class SelectData:
    def __init__(self,root):
        self.top = Toplevel(root)
        self.label = Label(self.top, text="SelectData")
        self.button = Button(self.top, text="Ok", command=self.closer)
        self.top.protocol("WM_DELETE_WINDOW", lambda: Quit(self.top))
        self.label.pack()
        self.button.pack()
        self.top.mainloop()
    def closer(self):
        self.top.destroy()




root = Tk()
ChoiceData(root)
root.mainloop()

This is a simplied version of what I want to do. Choice Data remain open when Select Data close.

Upvotes: 1

Views: 733

Answers (2)

samuel
samuel

Reputation: 21

Finally, I found what was bad on my GUI, in the last line, I should use:

self.quit()

instead of:

self.destroy()

self.destroy() don't let you continue your program after the mainloop of Select Data. And thank you @Ethan Field for helping me.

Upvotes: 1

Ethan Field
Ethan Field

Reputation: 4730

If all you're looking to do is have an action on two Toplevel widgets close both Toplevel widgets and run a snippet of code then something like the below achieves the desired result.

from tkinter import *

class App:
    def __init__(self, root):
        self.root = App.root = root
        ChoiceData()
        SelectData()
    def close():
        ChoiceData.top.destroy()
        SelectData.top.destroy()
        print("Windows closed")

class ChoiceData:
    def __init__(self):
        self.top = ChoiceData.top = Toplevel(App.root)
        self.label = Label(self.top, text="ChoiceData")
        self.button = Button(self.top, text="Ok", command=App.close)
        self.top.protocol("WM_DELETE_WINDOW", App.close)
        self.label.pack()
        self.button.pack()

class SelectData:
    def __init__(self):
        self.top = SelectData.top = Toplevel(App.root)
        self.label = Label(self.top, text="SelectData")
        self.button = Button(self.top, text="Ok", command=App.close)
        self.top.protocol("WM_DELETE_WINDOW", App.close)
        self.label.pack()
        self.button.pack()

root = Tk()
App(root)
root.mainloop()

Here we have four triggers to cause the App.close() function to run.

The first two are the Button widgets we create inside each Toplevel which both have their command attributes set to App.close which will run this function, closing both windows and running whatever snippet we insert.

The other two are a little bit more interesting, we override the WM_DELETE_WINDOW event, which handles the closing of a window when the little red "X" is pressed, and instead we tell it to run App.close() which closes both windows and runs the snippet.

Upvotes: 1

Related Questions