Reputation: 1
I am trying to develop a dialog box to be used with tkinter that has an entry box and a button. I want to be able to enter a value in the entry box and have the entered value "returned" when the dialog is destroyed. The following code works, but does not perform as I've described. There are two buttons on the gui. The first launches the dialog box and the second retrieves the entered value. I wish to eliminate the second button and have a listener activate the getValues method when the "Save Input" button in the dialog is pressed. Here is the code:
from tkinter import *
class myDialog():
def __init__(self):
self.t = Toplevel()
self.t.title("Sample")
self.answer = None
self.v1 = StringVar()
self.e1 = Entry(self.t, textvariable=self.v1)
self.e1.focus()
self.e1.pack()
self.saveButton = Button(self.t, text="Save Input", command=self.buttonPressed)
self.saveButton.pack()
def buttonPressed(self):
print("Popup Button Pressed")
self.answer = self.e1.get()
self.t.destroy()
class myTk(Tk):
def __init__(self):
Tk.__init__(self)
self.button = Button(text="Display Dialog", command = self.displayPopButton)
self.button.pack()
self.getButton = Button(text="Print Values", command=self.getValues)
self.getButton.pack()
def displayPopButton(self):
self.b1 = myDialog()
def getValues(self):
print(self.b1.answer)
myTk().mainloop()
Upvotes: 0
Views: 128
Reputation: 47173
You can make myDialog
a modal dialog using grab_set()
and wait_window()
:
from tkinter import *
class myDialog():
def __init__(self):
self.t = Toplevel()
self.t.title("Sample")
self.answer = None
self.v1 = StringVar()
self.e1 = Entry(self.t, textvariable=self.v1)
self.e1.focus()
self.e1.pack()
self.saveButton = Button(self.t, text="Save Input", command=self.buttonPressed)
self.saveButton.pack()
# handle user clicking the 'x' button at the title bar
self.t.protocol('WM_DELETE_WINDOW', self.buttonPressed)
def buttonPressed(self):
print("Popup Button Pressed")
self.answer = self.e1.get()
self.t.destroy()
def show(self):
# make the toplevel act like a modal dialog
self.t.grab_set()
self.t.wait_window(self.t)
# return the answer when the toplevel is closed/destroyed
return self.answer
class myTk(Tk):
def __init__(self):
Tk.__init__(self)
self.button = Button(text="Display Dialog", command = self.displayPopButton)
self.button.pack()
def displayPopButton(self):
self.b1 = myDialog().show()
print(self.b1)
myTk().mainloop()
Upvotes: 0
Reputation: 13898
You could be passing in your main object as a param in your Dialog, and call the master method within the buttonPressed
method:
class myDialog():
def __init__(self, master):
self.t = Toplevel()
self.master = master
# ... #
def buttonPressed(self):
print("Popup Button Pressed")
self.answer = self.e1.get()
self.master.getValues()
self.t.destroy()
class myTk(Tk):
# ... #
def displayPopButton(self):
self.b1 = myDialog(self)
This achieves what you want, but personally I don't think it's good OOP. It makes your Dialog
reliant on having the expected master type and the required method. You could organize it a little differently to be more explicit::
class myDialog():
def __init__(self, func_to_call):
self.t = Toplevel()
self.btn_func = func_to_call
# ... #
def buttonPressed(self):
print("Popup Button Pressed")
self.answer = self.e1.get()
func_to_call()
self.t.destroy()
class myTk(Tk):
# ... #
def displayPopButton(self):
self.b1 = myDialog(self.getValues)
In any case, I would at least subclass myDialog
as a Toplevel
. And perhaps rethink how I want the objects to refer to each other.
Upvotes: 1