From clnethery at juno.com Sun Oct 3 05:32:06 2004 From: clnethery at juno.com (Chris Nethery) Date: Sun Oct 3 05:32:53 2004 Subject: [Tkinter-discuss] Storing structured, 'widget-specific-data', then loading it back in la ter Message-ID: <20041002.203223.1158.231187@webmail14.nyc.untd.com> Hello everyone! I have been working on the following for a while and just cannot get it to work correctly, so I am hoping that someone could offer some advice. I am trying to create a group of (re-usable) methods that take user input data and store it for future reference, then reload it later to the same widget where it was originally created. I wrote the following program to try to get the process working. The first button is supposed to store the data, and the second button is meant to plug the data back into the widget. I seem to be having difficulty plugging the data back into the widget, because I cannot identify it(the widget) properly. Any thoughts? Thanking you in advance, Chris Nethery import marshal import Tkinter import Pmw root = Tkinter.Tk() screenWidth, screenHeight = root.maxsize() screenSize = "%dx%d" % (screenWidth, screenHeight) root.geometry(screenSize) Pmw.initialise(root) class DataManagement: def __init__(self,actualWidgetName,frame,widget,data): self.actualWidgetName = actualWidgetName self.f = frame collectedList = [] self.cL = collectedList self.widget = widget self.data = data self.dataStructure = [self.widget,self.data] if self.dataStructure not in self.cL: self.cL.append(self.dataStructure) file = open(self.widget + '.ats','wb') bytes = marshal.dump(self.dataStructure,file) file.close() self.testButton = Tkinter.Button(self.f, font=(('Verdana'), '7'), text='Test', command=self.getStoredData(self.widget)) self.testButton.place(relx=0.41,rely=0.01,anchor=Tkinter.NW) def getStoredData(self,widget): self.storeFile = open(widget + '.ats','rb') unmarshal = marshal.load(self.storeFile) self.unMarsheledData = unmarshal self.storeFile.close() self.outPutDataInNewWidget(self.unMarsheledData,self.widget,self.actualWidgetName) def outPutDataInNewWidget(self,unMarsheledData,widget,actualWidgetName): print unMarsheledData[0] print actualWidgetName['CB'] if unMarsheledData[0] == widget: actualWidgetName['CB'].selectitem(unMarsheledData[0], setentry = 1) else: print 'unMarsheledData[0] != fileName' # pass class CreateWidgets: def __init__(self,root): self.root = root self.mainFrame = Tkinter.Frame(self.root, relief=Tkinter.GROOVE, borderwidth=1, width=900, height=450) self.mainFrame.place(relx=0.01,rely=0.01,anchor=Tkinter.NW) stuff = ['1','2','3','4','5','6','7','8','9','10'] self.comboBox = Pmw.ComboBox( self.mainFrame, listbox_width=26, history=0, unique=0, dropdown=0, listbox_height=10, scrolledlist_items=stuff, ) self.comboBox.place(relx=0.01,rely=0.01,anchor=Tkinter.NW) frameHash = {self.comboBox:self.mainFrame} # Add more widgets later for item in [ (self.comboBox), ]: self.frame = frameHash[item] self.widget = str(item) self.data = item.component('entryfield').component('entry').get() self.actualWidgetName = {'CB':self.comboBox} self.saveButton = Tkinter.Button(self.mainFrame, font=(('Verdana'), '7'), text='Save', command=self.goStoreTheData) self.saveButton.place(relx=0.21,rely=0.01,anchor=Tkinter.NW) def goStoreTheData(self): DataManagement(self.actualWidgetName,self.mainFrame,self.widget,self.data) if __name__ == '__main__': W = CreateWidgets(root) root.mainloop() From fredrik at pythonware.com Sun Oct 3 08:42:09 2004 From: fredrik at pythonware.com (Fredrik Lundh) Date: Sun Oct 3 08:40:12 2004 Subject: [Tkinter-discuss] Re: Storing structured, 'widget-specific-data', then loading it back in la ter References: <20041002.203223.1158.231187@webmail14.nyc.untd.com> Message-ID: Chris Nethery wrote: > self.testButton = Tkinter.Button(self.f, font=(('Verdana'), '7'), > text='Test', command=self.getStoredData(self.widget)) to figure out why this doesn't work, consider what the following Python constructs do: getStoredData(widget) self.getStoredData(self.widget) variable = self.getStoredData(self.widget) # what ends up in variable? function(keyword=self.getStoredData(self.widget)) # what's passed to the method? Widget(command=self.getStoredData(self.widget)) # what's passed to the constructor? (hint: the "getStoredData(...)" part does the same thing, and returns the same thing, in all five cases) to work around this, you can add a local function: def my_callback(self=self): self.getStoredData(self.widget) self.testButton = Tkinter.Button(..., command=my_callback) (this creates a callable object, my_callback, that has a reference to the "self" instance variable. when the object is called, it will call the right getStoredData method with the right instance variable) you can also use a lambda, and in this case, you might not even need the argument binding (at least not if you're using a recent version of Python): ... Button(..., command=lambda: self.getStoredData(self.widget)) (but don't add the workaround until you've figured out why the original code doesn't work) From clnethery at juno.com Tue Oct 5 07:09:55 2004 From: clnethery at juno.com (Chris Nethery) Date: Tue Oct 5 07:11:48 2004 Subject: [Tkinter-discuss] Re: Storing structured, 'widget-specific-data', then loading it back in la ter Message-ID: <20041004.221035.9327.911723@webmail19.nyc.untd.com> Fredrik, Sorry for the delay. Needed to work on this one a bit. I think you identified, rather quickly, an area I don't really understand. I have been struggling quite a bit with variable-passing (for starters) and function-calls. For the first example, I think I'm accessing the widget's position in memory. I think this is also true of the second example, but I am making the variables accessible to other methods in the class. For the third example, I believe that 'variable' becomes the function call. For the fourth and fifth examples, I am calling a function within another function and passing self.widget (as a variable) into the function that is called... ...I think. Also, I am very confused by: 1) The creation of a local function. Why do I need to do this? What are the rules that require one to create a 'sub'-function (nested function?) ? 2) The self=self statement in the my_callback function. Doesn't the class already know that self=self, and if not, why don't I have to do this every time I pass self to other functions in the class? 3) Lambda. This may be more of a 'How does Lambda work?' question than anything, but here goes... ...With Button(..., command=lambda: self.getStoredData(self.widget)), am I creating another local function within the Button-widget method-call? And, why do I need to do this, rather than call a variable assigned to the function call? Thank you for your help! --Christopher Nethery From mfranklin1 at gatwick.westerngeco.slb.com Tue Oct 5 13:14:42 2004 From: mfranklin1 at gatwick.westerngeco.slb.com (Martin Franklin) Date: Tue Oct 5 13:14:48 2004 Subject: [Tkinter-discuss] Re: Storing structured, 'widget-specific-data', then loading it back in la ter References: <20041002.203223.1158.231187@webmail14.nyc.untd.com> Message-ID: On Sun, 3 Oct 2004 03:32:06 GMT, Chris Nethery wrote: > > Hello everyone! > > I have been working on the following for a while and just cannot get it > to work correctly, so I am hoping that someone could offer some advice. > > I am trying to create a group of (re-usable) methods that take user > input data and store it for future reference, then reload it later to > the same widget where it was originally created. I wrote the following > program to try to get the process working. The first button is supposed > to store the data, and the second button is meant to plug the data back > into the widget. I seem to be having difficulty plugging the data back > into the widget, because I cannot identify it(the widget) properly. Any > thoughts? Chris, This does not in anyway answer you questions.... but it may give you some ideas :-) from Tkinter import * import Pmw class PickleMixin: def __init__(self): self.widgets = {} self.storage = {} def store(self): # could add a pickle to file call here for name, widget in self.widgets.items(): self.storage[name] = widget.getData() def restore(self): # could add a pickle from file call here for name, widget in self.widgets.items(): widget.setData(self.storage[name]) class MyWidget(Frame, PickleMixin): def __init__(self, parent): Frame.__init__(self, parent) PickleMixin.__init__(self) self.list = Pmw.ScrolledListBox(self) self.list.pack() self.list.setData = self.setList self.list.getData = self.getList self.entry = Pmw.EntryField(self) self.entry.pack() self.entry.setData = self.setEntry self.entry.getData = self.getEntry self.widgets["list"] = self.list self.widgets["entry"] = self.entry self.list.setlist([1, 2, 3, 4, 5, 6, 7]) self.entry.setentry("yada yada") def getList(self): return self.list.get() def setList(self, data): self.list.setlist(data) def getEntry(self): return self.entry.get() def setEntry(self, data): self.entry.setentry(data) if __name__=="__main__": root=Tk() mw = MyWidget(root) mw.pack() b = Button(root, command=mw.store, text="Store Data") b.pack() b = Button(root, command=mw.restore, text="Re-Store Data") b.pack() root.mainloop() Martin. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/ From stewart at midtoad.homelinux.org Tue Oct 5 17:50:50 2004 From: stewart at midtoad.homelinux.org (stewart@midtoad.homelinux.org) Date: Tue Oct 5 17:50:04 2004 Subject: [Tkinter-discuss] Re: Storing structured, 'widget-specific-data', then loading it back in la ter In-Reply-To: <20041004.221035.9327.911723@webmail19.nyc.untd.com> References: <20041004.221035.9327.911723@webmail19.nyc.untd.com> Message-ID: <1096991450.4162c2daea965@midtoad.homelinux.org> Quoting Chris Nethery : > 3) Lambda. This may be more of a 'How does Lambda work?' question than > anything, but here goes... ...With Button(..., command=lambda: > self.getStoredData(self.widget)), am I creating another local function within > the Button-widget method-call? And, why do I need to do this, rather than > call a variable assigned to the function call? Chris, I've found that the use of lambda is a solution when you want to pass an argument to a callback function. If you simply create a command callback and include an argument in its construction, that callback function gets executed as soon as the GUI is drawn, which is not what we want! so, you can create a button like so (inside some Class that creates the GUI): b= Button(root, command = self.dosomething)) and will run properly, but you can't do the following: b= Button(root, command = self.dosomething(arg)) Instead, you'd need to do this: b= Button(root, command = lambda self=self, arg=arg: self.dosomething(arg)) Cameron Laird pointed out last week that you can also define an intermediate function to pass the argument to instead of using a lambda function. Here's a little app (uses Pmw) that demonstrates three different ways of passing arguments from a callback command: ---- title = 'Argument passing demonstration' # Import Pmw from this directory tree. import sys, time, string sys.path[:0] = ['../../..'] import Tkinter import tkFont from tkMessageBox import * import Pmw class Demo: def anotherFunction(self): self.printMe(self.arg) def __init__(self, parent): # Create and pack the MenuBar. menuBar = Pmw.MenuBar(parent, hull_relief = 'raised', hull_borderwidth = 1) menuBar.pack(fill = 'x') self.menuBar = menuBar # Add some buttons to the MenuBar. menuBar.addmenu('File', 'Close this window or exit') menuBar.addmenuitem('File', 'command', 'Pass arg to new object', command = PrintOne("I'm a new object"), label = 'Pass arg to new object') menuBar.addmenuitem('File', 'command', 'Pass arg through lambda', command = lambda self=self, arg="I'm a lambda": printMe(self, arg), label = 'Pass arg through lambda') self.arg="I'm an intermediate" menuBar.addmenuitem('File', 'command', 'Pass through intermediate function', command = self.anotherFunction, label = 'Pass arg through intermediate function') menuBar.addmenuitem('File', 'separator') menuBar.addmenuitem('File', 'command', 'Exit the application', command = root.destroy, label = 'Exit') # Create and pack the main part of the window. self.mainPart = Tkinter.Label(parent, text = 'This is the\nmain part of\nthe window', padx = 30, pady = 30) self.mainPart.pack(fill = 'both', expand = 1) def printMe(self, arg): print(arg) class PrintOne: def __init__(self, text): self.text = text def __call__(self): '''this method will be automatically called when an instance of the PrintOne object is created''' print self.text ###################################################################### # Create demo in root window for testing. if __name__ == '__main__': root = Tkinter.Tk() Pmw.initialise(root) root.title(title) widget = Demo(root) exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) exitButton.pack(side = 'bottom') root.mainloop() From mfranklin1 at gatwick.westerngeco.slb.com Wed Oct 6 08:58:40 2004 From: mfranklin1 at gatwick.westerngeco.slb.com (Martin Franklin) Date: Wed Oct 6 08:58:45 2004 Subject: [Tkinter-discuss] Re: Storing structured, 'widget-specific-data', then loading it back in la ter References: <20041004.221035.9327.911723@webmail19.nyc.untd.com> <1096991450.4162c2daea965@midtoad.homelinux.org> Message-ID: On Tue, 05 Oct 2004 09:50:50 -0600, wrote: > Quoting Chris Nethery : > >> 3) Lambda. This may be more of a 'How does Lambda work?' question than [SNIP] > class PrintOne: > def __init__(self, text): > self.text = text > > def __call__(self): > '''this method will be automatically called when an instance of > the > PrintOne object is created''' Stewart, I don't want to be pedantic ;-) but..... the __call__ method gets called when the instance of PrintOne is - called - not created. It's the __init__ method that gets called when the instance is created. Cheers Martin. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/ From stewart at midtoad.homelinux.org Fri Oct 8 03:02:38 2004 From: stewart at midtoad.homelinux.org (stewart@midtoad.homelinux.org) Date: Fri Oct 8 03:01:35 2004 Subject: [Tkinter-discuss] Re: lambda and __call__ method In-Reply-To: References: <20041004.221035.9327.911723@webmail19.nyc.untd.com> <1096991450.4162c2daea965@midtoad.homelinux.org> Message-ID: <1097197358.4165e72e8414e@midtoad.homelinux.org> Quoting Martin Franklin : > I don't want to be pedantic ;-) but..... the __call__ method gets called > when the instance of PrintOne is - called - not created. It's the > __init__ method that gets called when the instance is created. Martin, you're right of course. I didn't write what I meant to say. cheers, Stewart From stewart at midtoad.homelinux.org Fri Oct 8 03:09:11 2004 From: stewart at midtoad.homelinux.org (stewart@midtoad.homelinux.org) Date: Fri Oct 8 03:11:18 2004 Subject: [Tkinter-discuss] how to wait for user input? Message-ID: <1097197751.4165e8b7bc322@midtoad.homelinux.org> hi all: I've got a Tkinter app working. One of its methods opens a Pmw combo-box and present a list of choices. I've added buttons to delete choices, select choices, and create a new choice. It's this latter button that is causing problems. When I create a choice, I invoke a method that asks for input on the name of a choice using an easygui entry field. So far so good. The next thing is to ask the user to select one of two possible config setting for her choice; I'm doing that with a top-level widget that contains a button for each of the two settings. The problem I'm having is that my method doesn't appear to stop and wait for the user to press a button, but intead goes ahead to the next step, which is to display the chosen config setting (which of course fails, since no choice has yet been made). How do I get the method to stop and wait for the config setting to be made in the toplevel window? I think that I need the toplevel button to be modal, so that as soon as it's drawn, execution stops on my choice-creation method. If this seems too abstract, I can post a sample app that demonstrates the behaviour. cheers Stewart From jepler at unpythonic.net Fri Oct 8 03:32:23 2004 From: jepler at unpythonic.net (Jeff Epler) Date: Fri Oct 8 03:32:24 2004 Subject: [Tkinter-discuss] how to wait for user input? In-Reply-To: <1097197751.4165e8b7bc322@midtoad.homelinux.org> References: <1097197751.4165e8b7bc322@midtoad.homelinux.org> Message-ID: <20041008013223.GD6737@unpythonic.net> You can use .grab_set() (force keyboard and mouse events to a single window in the application) and .wm_transient() (give the window the appearance of a "transient" window aka "dialog" or "secondary window, and force it to appear above the main application window in stacking order). To wait for "something to happen", you can use wait_window (handles events and returns when the window is destroyed) or wait_variable (handles events and returns when the value of a variable is changed), or you can have the command= of the OK and Cancel buttons perform the action, destroy or hide the window, and release the grab, and use neither of the above. .grab_release() will let the main window handle events again. Destroying the secondary window would automatically release grab. I don't know whether merely withdrawing it would. Jeff -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: not available Url : http://mail.python.org/pipermail/tkinter-discuss/attachments/20041007/cb4b10ff/attachment.pgp From stewart at midtoad.homelinux.org Fri Oct 8 06:43:51 2004 From: stewart at midtoad.homelinux.org (stewart@midtoad.homelinux.org) Date: Fri Oct 8 06:42:42 2004 Subject: [Tkinter-discuss] how to wait for user input? In-Reply-To: <20041008013223.GD6737@unpythonic.net> References: <1097197751.4165e8b7bc322@midtoad.homelinux.org> <20041008013223.GD6737@unpythonic.net> Message-ID: <1097210631.41661b0758195@midtoad.homelinux.org> Quoting Jeff Epler : > You can use .grab_set() Thanks, Jeff, that was just the tip I needed. I did a look-up on .grab_set() and found some useful additional info in the pages at pythonware.com, e.g. http://www.pythonware.com/library/tkinter/introduction/dialog-windows.htm and also http://www.pythonware.com/library/tkinter/introduction/x9374-event-processing.htm. cheers Stewart From clnethery at juno.com Sat Oct 9 01:13:31 2004 From: clnethery at juno.com (Chris and Lisa Nethery) Date: Sat Oct 9 00:59:39 2004 Subject: [Tkinter-discuss] Re: Storing structured, 'widget-specific-data', then loading it back in later Message-ID: Hello all. I've been extraordinarily busy this week, so just checked my email. Wow! Thank you, everyone, for your help! One of the things that I absolutely love about this forum is the willingness people have to help out the 'newbies', such as myself. I now have likely a week's worth of things to tinker with, learn from and try out in various different ways. Again, thank you for your help! Sincerely, Christopher Nethery From kweelist at xs4all.nl Mon Oct 11 14:27:00 2004 From: kweelist at xs4all.nl (Roland Kwee) Date: Mon Oct 11 18:25:10 2004 Subject: [Tkinter-discuss] Re: Tkinter screen saver? Message-ID: <7889.80.126.188.84.1097497620.squirrel@webmail.xs4all.nl> I am not making a screen saver, but a photo viewer. While overrideredirect(1) is great for going fullscreen, it doesn't seem possible to bind a keyboard event, e.g., to go to the next photo, or exit fullscreen mode. It seems that only mouse events work with overrideredirect(1), but then I need to display a button. How can we make, say, the escape button end fullscreen mode? Thanks in advance, Roland Fredrik Lundh wrote: > wrote: > >> I'm wondering if I can get Tkinter to make a window that covers the whole >> screen so that we can have a Python-based screen saver? > >from Tkinter import * >root = Tk() >w, h = root.winfo_screenwidth(), root.winfo_screenheight() >root.overrideredirect(1) >root.geometry("%dx%d+0+0" % (w, h)) >root.mainloop() From jepler at unpythonic.net Mon Oct 11 18:39:47 2004 From: jepler at unpythonic.net (Jeff Epler) Date: Mon Oct 11 18:39:51 2004 Subject: [Tkinter-discuss] Re: Tkinter screen saver? In-Reply-To: <7889.80.126.188.84.1097497620.squirrel@webmail.xs4all.nl> References: <7889.80.126.188.84.1097497620.squirrel@webmail.xs4all.nl> Message-ID: <20041011163946.GC27520@unpythonic.net> You should be able to "grab_set_global()", sending all mouse and keyboard events to the given Tkinter top-level window. This is a good way to render your system unusable, if a bug prevents the grab from being released. On Unix, this can require ctrl-alt-backspace (kill X server, log out) or use of another machine or the text-mode console to kill the program. Long-lasting global grabs also cause problems with xscreensaver (which, in some versions, will lock even if it can't get grab, and then you'll have problems *un*locking). I'm not sure what problems it presents on Windows, and what solutions for them exist, while you're developing your software... Jeff -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: not available Url : http://mail.python.org/pipermail/tkinter-discuss/attachments/20041011/15769cab/attachment.pgp From fredrik at pythonware.com Mon Oct 11 22:37:41 2004 From: fredrik at pythonware.com (Fredrik Lundh) Date: Mon Oct 11 22:37:46 2004 Subject: [Tkinter-discuss] Re: Tkinter screen saver? References: <7889.80.126.188.84.1097497620.squirrel@webmail.xs4all.nl> Message-ID: Roland Kwee wrote: >I am not making a screen saver, but a photo viewer. > While overrideredirect(1) is great for going fullscreen, > it doesn't seem possible to bind a keyboard event, e.g., > to go to the next photo, or exit fullscreen mode. > It seems that only mouse events work with overrideredirect(1), > but then I need to display a button. > How can we make, say, the escape button end fullscreen mode? make sure the widget has focus: from Tkinter import * root = Tk() w, h = root.winfo_screenwidth(), root.winfo_screenheight() root.overrideredirect(1) root.geometry("%dx%d+0+0" % (w, h)) root.focus_set() # <-- move focus to this widget root.bind("", lambda e: e.widget.quit()) root.mainloop() From stewart at midtoad.homelinux.org Wed Oct 13 01:27:37 2004 From: stewart at midtoad.homelinux.org (stewart@midtoad.homelinux.org) Date: Wed Oct 13 02:26:23 2004 Subject: [Tkinter-discuss] prevent a Tkinter app from maximizing? Message-ID: <1097623657.416c686977de8@midtoad.homelinux.org> Is it possible to prevent a Tkinter app from being maximized? I'm guessing it would require some kind of WM_xxx protocol , but I don't see reference to anything but WM_DELETE_WINDOW in the tkinter documenatation at pythonware.com. thanks S From jepler at unpythonic.net Wed Oct 13 03:46:54 2004 From: jepler at unpythonic.net (Jeff Epler) Date: Wed Oct 13 03:46:48 2004 Subject: [Tkinter-discuss] prevent a Tkinter app from maximizing? In-Reply-To: <1097623657.416c686977de8@midtoad.homelinux.org> References: <1097623657.416c686977de8@midtoad.homelinux.org> Message-ID: <20041013014654.GD32019@unpythonic.net> The wm_minsize and wm_maxsize methods can set the range of sizes users are permitted to give a particular toplevel. Note that if the window is already bigger or smaller than this, its size is not immediately changed. But when the user attempts to resize it, the minimum and maximum will be enforced. You can also use the wm_resizable method to make the window non-resizable. How setting or removing these flags affects the window's decorations is highly dependant on window manager. On my window manager, only wm_resizable(0,0) removes the maximize button, but wm_maxsize(400,400) makes "maximize" keep the content area of the window only 400x400. I think the behavior on most flavors of Windows is similar to this behavior. Jeff -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: not available Url : http://mail.python.org/pipermail/tkinter-discuss/attachments/20041012/1b5c1625/attachment.pgp From stewart at midtoad.homelinux.org Wed Oct 13 06:47:12 2004 From: stewart at midtoad.homelinux.org (stewart@midtoad.homelinux.org) Date: Wed Oct 13 06:51:12 2004 Subject: [Tkinter-discuss] Re: prevent a Tkinter app from maximizing? In-Reply-To: <20041013014654.GD32019@unpythonic.net> References: <1097623657.416c686977de8@midtoad.homelinux.org> <20041013014654.GD32019@unpythonic.net> Message-ID: <1097642832.416cb350337e8@midtoad.homelinux.org> Quoting Jeff Epler : > The wm_minsize and wm_maxsize methods can set the range of sizes users > are permitted to give a particular toplevel. hey, good stuff Jeff! Thanks for that little tip. cheers Stewart From francesco.grillo at ciaolab.com Wed Oct 13 17:01:47 2004 From: francesco.grillo at ciaolab.com (francesco.grillo@ciaolab.com) Date: Wed Oct 13 17:07:43 2004 Subject: [Tkinter-discuss] pb with tcl / tk under win2000 Message-ID: <40F9D5CC00003B72@FE-mail04.sfg.albacom.net> Hi to all , i have a blocking pb . I use python 2.3 with tk/tcl 8.4.7 under windows2000;i wrote an application that in the begining under window systems was very instable , frequently crashed now and then without a reason . I found out that recompiling the tcl / tk libraries with "TCL_THREADS=1" flag these instability went away . Unfortunatelly there is a side effect that is : Memory allocation grow each time a call to tk is done . Since my application heavly use tk and is supposed to stay on days and days without shuting down , what it happens is that, after a while the memory used by applications is increased by Megas . Below i wrote a very simple .py that demostrates how is easy to grab memory from the system just calling the bell method in an infinite loop . Thank for the help , Francesco Grillo from Tkinter import * import threading import time import gc import os class Ticker: def __init__(self): self.l = Label(text="W") print 'init ' def start(self): self.thread = threading.Thread(target=self.tickerThread) self.thread.start() def tickerThread(self): while(1): self.l.bell() root = Tk() root.geometry("200x150+0+0") ticker1 = Ticker() ticker1.start() root.mainloop() From stewart at midtoad.homelinux.org Wed Oct 13 18:59:00 2004 From: stewart at midtoad.homelinux.org (stewart@midtoad.homelinux.org) Date: Wed Oct 13 20:11:39 2004 Subject: [Tkinter-discuss] how to disable individual sub-menu elements? Message-ID: <1097686740.416d5ed4e5b9e@midtoad.homelinux.org> I've got an app with a Pmw menubar. I can disable menu items, and enable them. For instance, to disable the first (0th) item in the Tools menu, I can write: self.menuBar.component('Tools-menu').entryconfig(0,state='disabled') Note that to access items in the Tools menu, I have to use the notation 'Tools-menu'. This is a sticking point, since it seems to indicate that I have to add '-menu' to a menu's name in order to access it. What would I do if the menu name had a space in it? So far, so good, however. But I don't see how to disable individual items under a cascaded sub-menu. For instance, under my Tools menu, I have a Build menu item with 2 cascaded sub-menu items. How would I disable the Build Initscript (0th) submenu? like the following? self.menuBar.component('Build-menu').entryconfig(0,state='disabled') (this doesn't work, BTW) And what if my menu name has a space in it? Here's the code that creates the submenus: self.menuBar.addcascademenu('Tools', 'Build', 'Build init script or linefill', traverseSpec = 'z', tearoff = 1, state = 'disabled', font = self.font) for viewer in ('Initscript', 'Linefill'): self.menuBar.addmenuitem('Build', 'command', 'Build ' + viewer, command = eval(toolsBldCmds[viewer]), font = self.font, label = 'Build ' + viewer) ''' toolsBldCmds = { 'Initscript': 'self.load', 'Linefill': 'self.edit_linefill'} ''' thx Stewart From stewart at midtoad.homelinux.org Wed Oct 13 18:25:11 2004 From: stewart at midtoad.homelinux.org (stewart@midtoad.homelinux.org) Date: Wed Oct 13 21:34:11 2004 Subject: [Tkinter-discuss] Re: pb with tcl / tk under win2000 In-Reply-To: <40F9D5CC00003B72@FE-mail04.sfg.albacom.net> References: <40F9D5CC00003B72@FE-mail04.sfg.albacom.net> Message-ID: <1097684711.416d56e724cfe@midtoad.homelinux.org> hi Francesco: I tried your sample app, but added one line so there'd be a slight delay between ticks. def tickerThread(self): while(1): time.sleep(1) self.l.bell() I also added a pack command to your init statement so your label would show up: class Ticker: def __init__(self): self.l = Label(text="W") self.l.pack() I'm also running Win2k, like you, and a 'stock' version of Tkinter which came with my Python 2.3. When I run your sample, Windows Task Manager reports a rock-steady memory usage by Python.exe of 4660 kb over a 5-minute period. I suppose this doesn't prove anything of help to you, but it indicates to me that the stock version of Tkinter doesn't have a problem with memory consumption. Of course, if I understood you correctly, your problem with the stock version was not memory consumption, but stability of the app. Is that correct? I wonder if recompiling Tkinter is the right approach. Perhaps all you've done is fix a symptom, rather than a problem. I wonder if it might not be fruitful to do more investigation as to why your app is crashing. Could you add some debug features so that information is written regularly to a log file that you can analyse after the app crashes? I use a similar approach, with the following methods defined: def open_debug(self): '''Open a debug log file for writing. Flush the contents of it if it already exists. this method is called on app initialisation''' try: self.logFile = open(self.logName, 'w+') except: cantopen(logName) def close_debug(self): '''Close the debug log file and truncate it to zero length. If we find a debug file with a non-zero length, it means that our app didn't close properly last time, and we will have to delete it manually.''' self.logFile.flush() self.logFile.truncate(0) self.logFile.close() def set_debug(self, mode): '''turn on debug mode''' if mode == 'Turn debug on': self.debug = 1 self.ask_debug() elif mode == 'Turn debug off': self.debug = 0 self.ask_debug() else: self.view_debug() def clear_debug(self): '''turn off debug mode''' self.debug = 0 self.ask_debug() def ask_debug(self): '''display debug mode''' statusDebug = ['off','on'] showinfo(title='Debug Status', message='Debug is now ' +statusDebug[self.debug]) def write_debug(self, msg=''): '''write to a debug file. Assume it is opened when the app starts (see further above), and that it will be closed when the app ends (see self.end).''' self.logFile.write(msg+'\n') self.logFile.flush() def view_debug(self): '''display the contents of the debug file''' #showFile is an easygui method s = showFile(self.logName) s.show() #showFile.show(fid) When I want to log something, I use this command: if self.debug: self.write_debug('in function ' +fcnName +': some status message') note that in the write_debug method, I call flush() to ensure that the log message is immediately written to file, so that if the app crashes, I have as much information as possible for later debugging. Also note that my app's quit command calls close_debug() to delete the log file upon normal termination. Since debugging messages can cause the debug log to grow rapidly, I initiate my app with debug turned off. I have a menu item to turn it on and off: menuBar.addcascademenu('Options', 'Debug', 'Set debug mode', traverseSpec = 'z', tearoff = 1, font=self.font) for mode in ('Turn debug on', 'Turn debug off', 'View debug file'): menuBar.addmenuitem('Debug', 'command', mode, command = lambda self=self, mode=mode: self.set_debug(mode), font=self.font, label = mode) ''' optionsDebugCmds = { 'Turn debug on': 'self.set_debug', 'Turn debug off': 'self.clear_debug', 'View debug file': 'self.view_debug'} ''' hope this helps! cheers Stewart From stewart at midtoad.homelinux.org Wed Oct 13 23:43:34 2004 From: stewart at midtoad.homelinux.org (stewart@midtoad.homelinux.org) Date: Thu Oct 14 00:01:43 2004 Subject: [Tkinter-discuss] Grayson's discussion forum on Tkinter Message-ID: <1097703814.416da186692f1@midtoad.homelinux.org> There's a discussion forum associated with Grayson's book on 'Python and Tkinter Programming' over at Manning Books: http://www.manning-sandbox.com/forum.jspa?forumID=51&start=0 However, when I took a look at the discussion items, I don't see anything posted by Grayson himself in well over a year. Has he given up his involvement with Tkinter? If so, does this mean that there'll never be a 2nd edition of his book? Maybe we should encourage readers of that book to come to this discussion list instead. cheers S From Cameron at Phaseit.net Thu Oct 14 00:03:27 2004 From: Cameron at Phaseit.net (Cameron Laird) Date: Thu Oct 14 00:03:32 2004 Subject: [Tkinter-discuss] Grayson's discussion forum on Tkinter In-Reply-To: <1097703814.416da186692f1@midtoad.homelinux.org> References: <1097703814.416da186692f1@midtoad.homelinux.org> Message-ID: <20041013220327.GA1011@lairds.us> On Wed, Oct 13, 2004 at 03:43:34PM -0600, stewart@midtoad.homelinux.org wrote: . . . > There's a discussion forum associated with Grayson's book on 'Python and Tkinter > Programming' over at Manning Books: > > http://www.manning-sandbox.com/forum.jspa?forumID=51&start=0 . . . > Maybe we should encourage readers of that book to come to this discussion list > instead. . . . 'Makes sense to me. From francesco.grillo at ciaolab.com Thu Oct 14 16:53:58 2004 From: francesco.grillo at ciaolab.com (francesco.grillo@ciaolab.com) Date: Thu Oct 14 16:54:03 2004 Subject: [Tkinter-discuss] why this prog.py crash on win32 ? Message-ID: <416AB9910000030B@FE-mail01.sfg.albacom.net> Hi guys, i am very surprised how this simple program can hung python (TCL/TK) . It works fine on a linux system but under windows not . Can anyone explain why and eventually which by pass apply ? If i want to write an aplication with a specialized thread that handles the graphic and that is different than the mainloop what i have to do ? thanks in advance , Francesco . # File: hello1.py from Tkinter import * import os import time import win32ui import threading from Tkinter import * import string import sys import glob import commands import win32api class App: def __init__(self,root ): self.r = root self.w = Toplevel(None, background = "#000053") self.w.geometry("200x200+0+0") self.w.resizable(0,0) self.frame = Frame(self.w,width=100,height=100,background = "#000053") self.frame.pack() self.button = Button(self.frame, text="QUIT", fg="red", command=self.frame.quit) self.button.pack(side=LEFT) self.button = Button(self.frame, text="max", fg="red", command=self.maxi) self.button.pack(side=LEFT) self.hi_there = Button(self.frame, text="min", command=self.mini) self.hi_there.pack(side=LEFT) def mini(self): print "MINI hi there, everyone!" self.r.deiconify() self.w.iconify() print "MINI after hi there, everyone!" def maxi(self): print "MAX hi there, everyone!" self.r.iconify() self.w.deiconify() print "MAX after hi there, everyone!" def grillo(root): print 'grillo ThreadID %x ' % win32api.GetCurrentThreadId() while(1): print 'iconify' time.sleep(2.0) root.mini() print 'deiconify' time.sleep(2.0) root.maxi() root = Tk() root.geometry("20x20") root.resizable(0,0) app = App(root) print 'main ThreadID %x ' % win32api.GetCurrentThreadId() gThread = threading.Thread(target=grillo,args=[app]) gThread.start() print 'main start mainloop %x ' % win32api.GetCurrentThreadId() root.mainloop() From jepler at unpythonic.net Thu Oct 14 17:29:53 2004 From: jepler at unpythonic.net (Jeff Epler) Date: Thu Oct 14 17:30:05 2004 Subject: [Tkinter-discuss] why this prog.py crash on win32 ? In-Reply-To: <416AB9910000030B@FE-mail01.sfg.albacom.net> References: <416AB9910000030B@FE-mail01.sfg.albacom.net> Message-ID: <20041014152952.GB754@unpythonic.net> I don't know much about the current state of Tkinter and threads, much less on win32. However, this 2002 article may be relevant to you: http://effbot.org/zone/tkinter-threads.htm This block of comment comes from a relatively recent CVS version of _tkinter.c (parts re-flowed to fit in 80 columns): /* The threading situation is complicated. Tcl is not thread-safe, except when configured with --enable-threads. So we need to use a lock around all uses of Tcl. Previously, the Python interpreter lock was used for this. However, this causes problems when other Python threads need to run while Tcl is blocked waiting for events. To solve this problem, a separate lock for Tcl is introduced. Holding it is incompatible with holding Python's interpreter lock. The following four macros manipulate both locks together. ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made that could call an event handler, or otherwise affect the state of a Tcl interpreter. These assume that the surrounding code has the Python interpreter lock; inside the brackets, the Python interpreter lock has been released and the lock for Tcl has been acquired. Sometimes, it is necessary to have both the Python lock and the Tcl lock. (For example, when transferring data from the Tcl interpreter result to a Python string object.) This can be done by using different macros to close the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl lock. By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event handlers when the handler needs to use Python. Such event handlers are entered while the lock for Tcl is held; the event handler presumably needs to use Python. ENTER_PYTHON releases the lock for Tcl and acquires the Python interpreter lock, restoring the appropriate thread state, and LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between ENTER_PYTHON and LEAVE_PYTHON. These locks expand to several statements and brackets; they should not be used in branches of if statements and the like. If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is only valid in the thread that created it, and all Tk activity must happen in this thread, also. That means that the mainloop must be invoked in the thread that created the interpreter. Invoking commands from other threads is possible; _tkinter will queue an event for the interpreter thread, which will then execute the command and pass back the result. If the main thread is not in the mainloop, and invoking commands causes an exception; if the main loop is running but not processing events, the command invocation will block. In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient anymore, since multiple Tcl interpreters may simultaneously dispatch in different threads. So we use the Tcl TLS API. */ These comments may not apply to your version of Tcl and Tkinter, since they depend on the compile options for Tcl and the Python version. Jeff -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: not available Url : http://mail.python.org/pipermail/tkinter-discuss/attachments/20041014/7f4bce45/attachment.pgp From trial at ugyvitelszolgaltato.hu Fri Oct 15 09:43:36 2004 From: trial at ugyvitelszolgaltato.hu (Attila Szabo) Date: Fri Oct 15 09:43:46 2004 Subject: [Tkinter-discuss] text widget Message-ID: <20041015074336.GC28235@csola.ugyvitelszolgaltato.hu> Hi, I'm new to TK and like to create text widget that allows just 50 characters typed in and just 1 line. How to do that ? I tried to unbind the Return binding, but it doesn't work to allow just 1 line. How to limit the number of typed in characters ? Have to do myself or has the widget a ready solution ? thanks -- A t t i l a :: trial@ugyvitelszolgaltato.hu :: S z a b o From fredrik at pythonware.com Fri Oct 15 10:36:59 2004 From: fredrik at pythonware.com (Fredrik Lundh) Date: Fri Oct 15 10:34:53 2004 Subject: [Tkinter-discuss] Re: text widget References: <20041015074336.GC28235@csola.ugyvitelszolgaltato.hu> Message-ID: Attila Szabo wrote: > I'm new to TK and like to create text widget > that allows just 50 characters typed in and just 1 line. > How to do that ? > I tried to unbind the Return binding, but it doesn't work to > allow just 1 line. > How to limit the number of typed in characters ? > Have to do myself or has the widget a ready solution ? if you only need one line, maybe you could use an Entry widget instead? see the MaxLengthEntry example on this page for one way to limit the length: http://effbot.org/zone/tkinter-entry-validate.htm (more recent versions of Tk also has a validate hook, but I don't have any ready-made examples for that feature...) From francesco.grillo at ciaolab.com Wed Oct 20 16:38:20 2004 From: francesco.grillo at ciaolab.com (francesco.grillo@ciaolab.com) Date: Wed Oct 20 16:38:24 2004 Subject: [Tkinter-discuss] tk problem !!! Message-ID: <40F9D5B1000040DF@FE-mail03.sfg.albacom.net> Hi to all, I use python on win32 and since on windows the multithread support in the tk/tcl does not work at all i have to rewrite the graphical part of my application as a single thread is there anyone that can give me some tips (some src code samples )on how to write a graphical application with the entire graph manged by the main thread (the one that does mainloop() ) and with some threads that comunicate with it by the queue mechanism ? thanks , Francesco From jepler at unpythonic.net Thu Oct 21 20:07:04 2004 From: jepler at unpythonic.net (Jeff Epler) Date: Thu Oct 21 20:07:20 2004 Subject: [Tkinter-discuss] tk problem !!! In-Reply-To: <40F9D5B1000040DF@FE-mail03.sfg.albacom.net> References: <40F9D5B1000040DF@FE-mail03.sfg.albacom.net> Message-ID: <20041021180703.GB341@unpythonic.net> I'm not in your situation, so I've never actually had to address this problem. However, I thought about how I'd solve it. First, one way to do it is to re-structure your code so that you no longer use threads. Any long-running calculations are re-structured so that they can run in pieces from Tk's "after", blocking the user interface for no more than a few ms at a time. This is often far from trivial, even when using the "generators as limited coroutines" approach. If you can't do that, then you have to arrange for GUI calls in a non-main thread to actually be sent to the main thread somehow. The obvious way is through a Queue.Queue. In the main thread, an "after" will fire every 100ms or so, service any items in the queue of calls, and then return to normal event handling. There are a few more wrinkles: Some calls will want the return value, others won't. Some calls will need to be done in a bundle, without handling events in the meantime. Here's the class I wrote, called TkThreadingGizmo: #------------------------------------------------------------------------ # Copyright (C) 2004 Jeff Epler # You may use this code according to the terms of the Python License import Queue class TkThreadingGizmo: def __init__(self, csize=100, rsize=1): self.calls = Queue.Queue(csize) self.results = Queue.Queue(rsize) self.block = False def install(self, window=None, interval=100): if window is None: window = Tkinter._default_root self.window = window self.interval = interval self.handle_calls_callback() def unuinstall(self): self.window = None def queue_call(self, func, *args, **kw): self.calls.put((True, func, args, kw)) state, value = self.results.get() if state: raise value else: return value def queue_call_async(self, func, *args, **kw): self.calls.put((False, func, args, kw)) def handle_calls(self): while self.block or not self.calls.empty(): wantresult, func, args, kw = self.calls.get() if wantresult: try: self.results.put((False, func(*args, **kw))) except (KeyborardInterrupt, SystemExit): raise except Exception, detail: self.results.put((True, detail)) else: try: func(*args, **kw) except (KeyborardInterrupt, SystemExit): raise except Exception, detail: exception.print_last() def handle_calls_callback(self): self.handle_calls() if self.window: self.window.after(self.interval, self.handle_calls_callback) #------------------------------------------------------------------------ The important details: queue_call sends a call from a thread to the main thread, and waits for the result. Most exceptions are intended to be reraised in the caller, but this is untested. queue_call_async sends a call from a thread to the main thread, but doesn't wait for a result. Most exceptions are intended to be printed (untested, again) but some exceptions are allowed to propagate in the main thread. Set the "block" flag *before* the first call that must happen in a bundle, then unset it *before* the last call (not *after* the last call). Here's a test program: #------------------------------------------------------------------------ # Copyright (C) 2004 Jeff Epler # You may use this code according to the terms of the Python License from Tkinter import * from tktg import TkThreadingGizmo import threading import time class App(threading.Thread): def run(self): i = 0 while not self.shutdown: self.block = True value = self.gizmo.queue_call(self.var.get) self.block = False self.gizmo.queue_call_async(self.var.set, value + 1) time.sleep(1) t = Tk() v = IntVar(t) l = Label(t, text="Value:", width=8) l.pack(side="left") l = Label(t, textvariable=v, width=5) l.pack(side="left") b = Button(t, text="Reset", width=8, command=lambda: v.set(0), default="active") t.bind("", lambda event: b.invoke()) b.pack(side="left") g = TkThreadingGizmo() a = App() a.gizmo = g; a.var = v; a.shutdown = 0 a.start() g.install(t) try: t.mainloop() finally: a.shutdown = 1 #------------------------------------------------------------------------ The thread just increments the value once a second or so. Because it reads the old value, and then sets the new value, the calls must be done as a bundle. Otherwise, you would be able to hit the Reset button between the read and the write, so that the value would jump to 0 for a moment but then return to the previous value plus one. Feel free to use this code if it's helpful to you. Jeff -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: not available Url : http://mail.python.org/pipermail/tkinter-discuss/attachments/20041021/0467685a/attachment.pgp From xeranic at yahoo.com Fri Oct 22 13:57:48 2004 From: xeranic at yahoo.com (Xin Wang) Date: Fri Oct 22 14:28:01 2004 Subject: [Tkinter-discuss] How to change Tk's size ? Message-ID: <20041022115748.17597.qmail@web90002.mail.scd.yahoo.com> How to change Tk's size ? I used 'config(width=500, height=500)', but it dose not works! #*start from Tkinter import * root = Tk() root.config(width=500, height=500) bt = Button(root, text="hello") bt.pack() root.mainloop() #*end _______________________________ Do you Yahoo!? Declare Yourself - Register online to vote today! http://vote.yahoo.com From jepler at unpythonic.net Fri Oct 22 18:07:07 2004 From: jepler at unpythonic.net (Jeff Epler) Date: Fri Oct 22 18:07:10 2004 Subject: [Tkinter-discuss] How to change Tk's size ? In-Reply-To: <20041022115748.17597.qmail@web90002.mail.scd.yahoo.com> References: <20041022115748.17597.qmail@web90002.mail.scd.yahoo.com> Message-ID: <20041022160706.GC341@unpythonic.net> Use .wm_geometry("widthxheight") or .pack_propagate(0). The configure'd width= and height= of a frame or a toplevel is only used if it does not have any packed or gridded slaves, or if pack_propagate(0) (when there are packed slaves) or grid_propagate(0) (when there are gridded slaves) are used. Jeff -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: not available Url : http://mail.python.org/pipermail/tkinter-discuss/attachments/20041022/929dc043/attachment.pgp From jepler at unpythonic.net Thu Oct 28 16:44:51 2004 From: jepler at unpythonic.net (Jeff Epler) Date: Thu Oct 28 16:45:00 2004 Subject: [Tkinter-discuss] Wiki now requires a login to change pages Message-ID: <20041028144450.GE19311@unpythonic.net> There have been a growing number of defacements to the tkinter wiki. In order to create a small barrier to these defacements, I have changed the configuration so that authors must log in (by visiting the "UserPreferences" link shown at the top of each page) before editing pages. I've done my best to clean up after the defacements (links to sites that are at best unrelated to tkinter) including the removal of the defaced versions of the page, since search engines might even index those pages. If you see a defaced page, please revert it to the undefaced version and leave something obvious in the change comment so I can remove the archived defaced version too. Not so sure I like wikis anymore, Jeff -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: not available Url : http://mail.python.org/pipermail/tkinter-discuss/attachments/20041028/c0479dbe/attachment.pgp