On Friday, March 4, 2016 at 3:50:43 PM UTC-6, kevin...@gmail.com wrote: > Thanks for your attention to this matter. > My code now look like this: [...]
All of the help offered in this thread ignores the elephant in the room. What are you trying to achieve here Kevin? To me, this looks like some sort of dialog, but if it is a dialog, the whole design is a miserable failure. And why in the hell would you call the w.quit() method when the user presses a "continue" button? Do you realize that the quit method does not "close the dialog" (if you can call this a dialog), no, but simply instructs Tkinter to stop processing events? Once a user clicks your "continue" button, he can no longer interact with the GUI, and the user is left in a state of befuddlement. Those who've attempted to help you have suggested that you utilize the quit method in your "continue button callback" so that the widgets will stay alive long enough for you to fetch the value, but that is horrible advice. Trust me, the quit method is not something you want to use unless you know what you're doing. It's should never be used in daily coding, and only in very specific advanced circumstances. The destroy method that you utilized initially *IS* the correct course of action here. You see, your interface is not a failure because of the destroy method, no, it is a failure because you failed to (1) fetch the values in the button callback BEFORE the widgets are destroyed, and (2) You failed to store those values somewhere that will be persistent after the function returns. But even if you followed both of these suggestions, you design is flawed. If you want to create a proper "dialog interface", the key is not to use the "quit" method, but to follow these simple design rules: (1) Present the user with a "focused window" that contains "form" filled with "input fields" that will facilitate the inputting of the required values. Typically, but not always, you'll want this window to block program execution until the user submits the form (FYI: Dialogs that block are commonly referred to as "modal dialogs") (2) Include at least one button to submit the values. This button is typically named "Okay", or "Yes" or "Submit". But when the user presses this button, the dialog will *NOT* be closed until the values have been validated. If the values are found to be inadequate, the dialog will inform the user of his mistakes and refocus the input-form for editing. A more advanced dialog will utilize fields that validate their *OWN* values in "real time". These "real time validations" are less likely to confuse a user, and they facilitate a more efficient interface since the user will be aware of mistakes as they occur. (3) Include at least one button to cancel the interaction. Sometimes, a user will open a dialog accidentally, or for some other reason decide that they need a way out. For instance: Imagine all the times that you've accidentally pressed the X button on a window. If the window closed without first asking you "Do you really want to close without saving changes", you'd be screwed! A proper "dialog window" will be constructed of three basic top-level components: +--------------------------+ |DIALOG_TITLE | +--------------------------+ | | | DIALOG_BODY | | | +--------------------------+ | DIALOG_BUTTONS | +--------------------------+ The DIALOG_TITLE is simply a string that will be displayed in the title bar of the dialog. The DIALOG_BODY is a fluid area in the middle that can be filled with user-editable fields, and the DIALOG_BUTTONS is an area at the bottom where appropriate buttons will be displayed. A proper dialog object will allow the caller to display the dialog in either "modal" or "non-modal" forms, and it will expose hooks that will allow the programmer to customize the validation and submission of the form data. An even more advanced version will require the programmer to extend a "form object" and pass it into the constructor. Fortunately, the tkSimpleDialog has already wrapped *SOME* of this functionality up for you. All you need to do is import the class and override a few "virtual methods" to achieve your desired goal. The tkSimpleDialod.Dialog class exposes 3 hooks that you can utilize to modify the behavior (1) body: In this method you create your widgets.It requires one argument which is a tk.Frame instance that the widgets can be made a child of. (2) validate: in this method you validate your widgets and return a Boolean flag. If you don't need any validation then don't bother to override it. (3) apply: In this method you can do something with the "dialog.result" *AFTER* the dialog closes. Typically though, you will handle this action from outside the dialog object. But in certain limited circumstances, it can simplify your code. ############################################################ # START EXAMPLE CODE ############################################################ import Tkinter as tk from tkSimpleDialog import Dialog from tkMessageBox import showerror class MyDialog(Dialog): def body(self, master): # CLOBBERS BASE METHOD! # This is called just before the dialog is shown. w = tk.Label(master, text= 'Age') w.grid(row=0, column=0) self.e1 = e1 = tk.Entry(master) e1.grid(row=0, column=1) w = tk.Label(master, text= 'Weight') w.grid(row=1, column=0) self.e2 = e2 = tk.Entry(master) e2.grid(row=1, column=1) return e1 # This widget will get focus! def _validateInteger(self, value): # INTERNAL HELPER FUNCTION try: int(value) except ValueError: return False else: return True def validate(self): # CLOBBERS BASE METHOD! # This is called after the okay button is pressed a = self.e1.get().strip() b = self.e2.get().strip() # # Validate Weight if a=='': showerror('', 'Age cannot be empty') return False elif not self._validateInteger(a): showerror('', 'Age must be a number!') return False # # Validate Height elif b=='': showerror('', 'Weight cannot be empty') return False elif not self._validateInteger(b): showerror('', 'Weight must be a number!') return False # # Let the dialog know everything is A-OKAY! else: self.result = [int(a), int(b)] return True def apply(self): # CLOBBERS BASE METHOD! # This is called after the dialog closes. # It's not normally needed since you can reliably set the return # value in "validate", but it's important to realize that this # method is one of the provided hooks. pass if __name__ == '__main__': def goodTimes(): d = MyDialog(root, title='Good Times Application') result = d.result print 'result =', `result` if result: age, weight = result if age < 18 or age > 80: print "Sorry, but you're either too young or too old" elif weight < 100 or weight > 120: print "Sorry, but you're too bony or too heavy." else: print 'Let the good times roll!' else: print 'USER CANCELED!' root = tk.Tk() w = tk.Button(root, text='For a good time, press me', command=goodTimes) w.pack(padx=5, pady=5) root.mainloop() ############################################################ # END EXAMPLE CODE ############################################################ Unfortunatley, the tkSimpleDialog is terriby written, uses poor naming conventions, does not expose enough hooks, and is therefore a sad excuse for what a modern "dialog library" should be. For example: the virtual methods of "body", "validate", and "apply" would be much more intuitive if they had been named "create_form", validate_form", and "process_form" respectively. Although, i would go a step further and mark them as "hooks" by naming them: "hook_createForm", "hook_validateForm", and "hook_processForm". I hate reading source and not knowing which methods are clobbering base methods. That REALLY pisses me off! And IMO, is a giant elephant-sized bowel movement of a code smell! But in your case, even with tkSimpleDialog's many flaws, it is still leaps and bounds better than what you have managed to do (sorry to be so frank), and it will save you the time and effort of re-inventing the wheel. I would suggest you use it only long enough to understand its flaws, and then re-write it to better suit your needs. That's what i did long ago, and my sanity has benefited greatly from discarding such horrible libraries such as this. -- https://mail.python.org/mailman/listinfo/python-list