I tried this super simple class example from net. (Yes I am a beginner in implementation of object oriented features in Python)

UPDATE: Now from fresh start of IDLE it did not crash, but did not quit properly still. Hmm. TaskManager any (or dozen) python zombies hanging around?? No only one Pythonwin this time.

from Tkinter import *

class HelloPackage:                       
    def __init__(self, parent=None):
        self.top = Frame(parent)          
        self.top.pack()
        self.data = 0
        self.make_widgets()               
    def make_widgets(self):
        Button(self.top, text='Quit', command=self.top.quit).pack(side=RIGHT)
        Button(self.top, text='Hello', command=self.message).pack(side=LEFT)
    def message(self):
        self.data = self.data + 1
        print 'Hello number', self.data

if __name__ == '__main__': HelloPackage().top.mainloop()

It starts OK, and functions well from running directly, but both IDLE and PythonWin crash/hangup on trying to quit with button1

PyScripter handles the program also well (from PortablePython)

OK, I understand somehow that it is some kind of conflict with Tk running IDLE and tk running this program, but does anybody know exactly, what causes it?

Recommended Answers

All 11 Replies

Looks like closing the window does the right thing, Quit button not

Quit will quit the tcl interpreter of Tkinter!
If IDLE is used, quit will freeze it, since IDLE uses Tkinter too!
Replace quit with destroy, destroy is used to destroy a particular
window in a multi-window program

Quit will quit the tcl interpreter of Tkinter!
If IDLE is used, quit will freeze it, since IDLE uses Tkinter too!
Replace quit with destroy, destroy is used to destroy a particular
window in a multi-window program

Does not work. It only takes out the buttons, not the window.

I do have somewhere code which works in this kind of situation. Wait a moment:

search through files, quit

here is self.quit
does not work

here is self.master.quit
does not work

Hey, there it is: root.protocol("WM_DELETE_WINDOW", quit_ap) It should work. Let's try ...... NO, we have no root, this is for executing different command when window closes, but that allready does the right thing.

Only thing that works smoothly in IDLE is to put root=Tk() in the program:

from Tkinter import *

class HelloPackage:                       
    def __init__(self, parent=None):
        self.top = Frame(parent)          
        self.top.pack()
        self.data = 0
        self.make_widgets()
        
    def make_widgets(self):
        Button(self.top, text='Quit', command=root.destroy).pack(side=RIGHT)
        Button(self.top, text='Hello', command=self.message).pack(side=LEFT)
    def message(self):
        self.data = self.data + 1
        print 'Hello number', self.data

if __name__ == '__main__':
    root=Tk()
    HelloPackage(root).top.mainloop()

Man, object-oriented in my opinion is one of Python's best features. It's not just for creating GUI. So if you aren't familiar with the object oriented features of Python, you should really play around with them. They make programming very fun.

I don't think you should be using Tkinter with IDLE,simply because IDLE itself uses Tkinter.

I have studied programming language theory and various programming languages but have not gotten around to use them. Only little Delphi Object Pascal and the Lazarus Gpl version. GUI has been the major use of it.

Your destroy dosen't work as expected since you are only destroying the frame and not the root.

As a minimum rewrite your code to something like this ...

from Tkinter import *

class HelloPackage:
    def __init__(self, parent=None):
        self.top = Frame(parent)
        self.top.pack()
        self.parent = parent
        self.data = 0
        self.make_widgets()

    def make_widgets(self):
        Button(self.top, text='Quit', command=self.parent.destroy).pack(side=RIGHT)
        Button(self.top, text='Hello', command=self.message).pack(side=LEFT)

    def message(self):
        self.data = self.data + 1
        print 'Hello number', self.data


if __name__ == '__main__':
    root = Tk()
    hp = HelloPackage(root)
    root.mainloop()

You can write Tkinter programs with the IDLE IDE as long as you remember to use destroy rather than quit.

My rewrite also worked with top.mainloop() left in place.

Your rewrite has a nice point in accessing the target of destroying through parent. That I tried also, but it did not come to my mind to change which objects' mainloop was.

There should be also way to access the root window, even the widgets are put with parent None. That means to do exactly same as closing the window from the icon. Maybe producing window close event by program?

I have myself used preferably instead of mainloop, wait_window command. Then programs close without crashing.
Any problem with that?

TCL code that makes up Tkinter is very forgiving and can lead to very poor programming styles.

If you want to use a class approach to Tkinter, I recommend a look at:
http://www.daniweb.com/forums/post1146095.html#post1146095

There root is simply self itself.

Yes that code looked for me lot nicer as the our own object inherits from Tk. That agrees better with the philosophy of programming languages I have learned.

I would like to do something more ambitious to test the limits of object oriented support. Could I for example add to string and list types a pritty print method, not make my own type, but let all programs to have those methods available?

You may want to put that project into a new thread with the appropriate title, rather than hiding it back in here. You will get more help that way.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.