Re: [Tutor] Question on tkinter event binding
Hi Patty, As far as books are concerned, I actually prefer (programming) books in the English language. Although the Dutch don't do it as much as e.g. the French or the Germans, I hate it when technical terms are translated into Dutch in a somewhat artificial way (Computer is Ordinateur in French and Rechner in German [although Computer is also OK]; in Dutch it's simply Computer) . It also makes it harder to find additional info on the internet. In addition, books in the English language are usually far cheaper than those in Dutch. As far as programming itself is concerned, I find it slightly more readable to use Dutch variable and function names. The risk of name clashes is also virtually absent! In my office we have a coding convention which states that Dutch names should be used. I must confess, however, I don't always consistently follow the convention. One example are getter and setter methods. It's just clearer to use 'get' and 'set' in the method name. When I download software, I use then 'as-is'. I might translate code snippets so it blends better with the rest of the code. If I send snippets to e.g. this mailing list, I usually translate the variable names + comments --only this time I was a bit lazy. ;-) Cheers!! Albert-Jan ~~ All right, but apart from the sanitation, the medicine, education, wine, public order, irrigation, roads, a fresh water system, and public health, what have the Romans ever done for us? ~~ From: Patty pa...@cruzio.com To: Albert-Jan Roskam fo...@yahoo.com; Python Mailing List tutor@python.org Sent: Fri, December 3, 2010 11:39:28 PM Subject: Re: [Tutor] Question on tkinter event binding Hello Albert-Jan: I am glad you made the comment below. I was fascinated with the fact that your code was partly in English/Python and also in Dutch. I am a linguist so have great interest in bilingualism. How does this work in practice? I mean as a programmer, with native language other than English, do you download or buy English language software programs and work with them as-is? Do you have translated tutorials to help you learn? If you had a Dutch language software program and created your own program so that everything is totally in Dutch, and you wanted to communicate with English language email group :) How would you do that? Or would you try and find a Dutch language resource? Besides that, I am definitely saving your code segments for the future. Thanks for sharing. Patty - Original Message - From: Albert-Jan Roskam To: Albert-Jan Roskam ; Python Mailing List Sent: Friday, December 03, 2010 12:18PM Subject: Re: [Tutor] Question on tkinterevent binding stuff snipped I'llpaste the working code below. It's partially in Dutch, but hey, so is Guidovan Rossem. ;-) stuff snipped ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Question on tkinter event binding
Hi Patty, As far as books are concerned, I actually prefer (programming) books in the English language. Although the Dutch don't do it as much as e.g. the French or the Germans, I hate it when technical terms are translated into Dutch in a somewhat artificial way (Computer is Ordinateur in French and Rechner in German [although Computer is also OK]; in Dutch it's simply Computer) . It also makes it harder to find additional info on the internet. In addition, books in the English language are usually far cheaper than those in Dutch. As far as programming itself is concerned, I find it slightly more readable to use Dutch variable and function names. The risk of name clashes is also virtually absent! In my office we have a coding convention which states that Dutch names should be used. I must confess, however, I don't always consistently follow the convention. One example are getter and setter methods. It's just clearer to use 'get' and 'set' in the method name. When I download software, I use then 'as-is'. I might translate code snippets so it blends better with the rest of the code. If I send snippets to e.g. this mailing list, I usually translate the variable names + comments --only this time I was a bit lazy. ;-) I tend to follow this piece of advice from PEP 8: Python coders from non-English speaking countries: please write your comments in English, unless you are 120% sure that the code will never be read by people who don't speak your language. It's about comments, but applies just as well to variable names etc. If output strings are eg Dutch, that's only the non-English part, and I might even make use of some translation library (ie, English strings, which get replaced by the appropriate strings upon a language settings. I know Django uses this system). It has such a huge advantage when, for example, asking questions on a list like this. Albert-Jan may occasionally translate his problems, but there's no guarantee that that wouldn't masquerade the actual problem. I actually find it a bit weird that a (programming?) company has a coding convention for non-English names; makes it harder if you want to hire non-Dutch speaking employees, distribute software ( code) internationally etc. Cheers, Evert Cheers!! Albert-Jan ~~ All right, but apart from the sanitation, the medicine, education, wine, public order, irrigation, roads, a fresh water system, and public health, what have the Romans ever done for us? ~~ From: Patty pa...@cruzio.com To: Albert-Jan Roskam fo...@yahoo.com; Python Mailing List tutor@python.org Sent: Fri, December 3, 2010 11:39:28 PM Subject: Re: [Tutor] Question on tkinter event binding Hello Albert-Jan: I am glad you made the comment below. I was fascinated with the fact that your code was partly in English/Python and also in Dutch. I am a linguist so have great interest in bilingualism. How does this work in practice? I mean as a programmer, with native language other than English, do you download or buy English language software programs and work with them as-is? Do you have translated tutorials to help you learn? If you had a Dutch language software program and created your own program so that everything is totally in Dutch, and you wanted to communicate with English language email group :) How would you do that? Or would you try and find a Dutch language resource? Besides that, I am definitely saving your code segments for the future. Thanks for sharing. Patty - Original Message - From: Albert-Jan Roskam To: Albert-Jan Roskam ; Python Mailing List Sent: Friday, December 03, 2010 12:18 PM Subject: Re: [Tutor] Question on tkinter event binding stuff snipped I'll paste the working code below. It's partially in Dutch, but hey, so is Guido van Rossem. ;-) stuff snipped ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Question on tkinter event binding
Hi Evert, I actually wanted the var names to be in English, but apparently the people who came up with the coding convention did not agree with me on this. Then again, the Zen of Python states that (1) readability counts and that (2) practicality beats purity. Most of the time, I'm 120% sure the code doesn't leave Holland. If it inadvertently does, Ctrl-H is my friend. It's impractical to overgeneralize one's applications. Let's say I have a list of all the medical specialisms we have here in N. I really wouldn't know all the exact English equivalents. My manager wouldn't like it if I spent my time doing all the translations. Besides, doesn't it with the current political climate to have dutch-only code? ;-) [Note: We had a landslide win of a xenophobic, right-wing party during the last elections] Meanwhile, I tinkered a bit more with the code. I used exec() to isolate the event handler function. It works and it's better, but I think it could be still better. I'm not so fond of eval() and exec(). from Tkinter import * def createWidgets(veldnamen): root=Tk() termenlijst = {Naam: set([Bill Gates, Elvis Presley]), *Postcode: set([2600AA, 8000BB]), Adres: set([Street, Avenue])} handleDeletions = {} for veldnaam in veldnamen: labelWidget=Label(root, text=veldnaam, takefocus=False) labelWidget.grid() # tcl names must start with a lowercase letter tclName = veldnaam[0].lower() + veldnaam[1:] content = StringVar() entryWidget=Entry(root, name=tclName, textvariable=content) entryWidget.grid() exec(doHandleDeletion()) handleDeletions[entryWidget] = handleDeletion for entryWidget, handleDeletion in handleDeletions.iteritems(): entryWidget.bind(Shift-Delete, handleDeletion) def doHandleDeletion(): func = \ def handleDeletion(event, widget=entryWidget, root=root, termenlijst=termenlijst,content=content): actieveVenster = root.focus_get() actieveVensternaam = str(actieveVenster)[1:].capitalize() if actieveVensternaam.startswith(*): actieveVensternaam = * + actieveVensternaam[1:].capitalize() vensterinhoud = content.get().strip() print Name: %s -- Contents: %s % (actieveVensternaam, vensterinhoud) try: termenlijst[actieveVensternaam].remove(vensterinhoud) actieveVenster.delete(0, END) print Deleted term '%s' % vensterinhoud except KeyError: print No such term '%s' % vensterinhoud pass return func createWidgets([Naam, *Postcode, Adres]) Cheers!! Albert-Jan ~~ All right, but apart from the sanitation, the medicine, education, wine, public order, irrigation, roads, a fresh water system, and public health, what have the Romans ever done for us? ~~ From: Evert Rol evert@gmail.com To: Albert-Jan Roskam fo...@yahoo.com Cc: Patty pa...@cruzio.com; Python Mailing List tutor@python.org Sent: Sat, December 4, 2010 2:10:04 PM Subject: Re: [Tutor] Question on tkinter event binding Hi Patty, As far as books are concerned, I actually prefer (programming) books in the English language. Although the Dutch don't do it as much as e.g. the French or the Germans, I hate it when technical terms are translated into Dutch in a somewhat artificial way (Computer is Ordinateur in French and Rechner in German [although Computer is also OK]; in Dutch it's simply Computer) . It also makes it harder to find additional info on the internet. In addition, books in the English language are usually far cheaper than those in Dutch. As far as programming itself is concerned, I find it slightly more readable to use Dutch variable and function names. The risk of name clashes is also virtually absent! In my office we have a coding convention which states that Dutch names should be used. I must confess, however, I don't always consistently follow the convention. One example are getter and setter methods. It's just clearer to use 'get' and 'set' in the method name. When I download software, I use then 'as-is'. I might translate code snippets so it blends better with the rest of the code. If I send snippets to e.g. this mailing list, I usually translate the variable names + comments --only this time I was a bit lazy. ;-) I tend to follow this piece of advice from PEP 8: Python coders from non-English speaking countries: please write your comments in English, unless you are 120% sure that the code will never be read by people who don't speak your language. It's about comments, but applies just as well to variable names etc. If output strings are eg Dutch, that's only the non-English part, and I
Re: [Tutor] Question on tkinter event binding
Evert Rol wrote: I actually find it a bit weird that a (programming?) company has a coding convention for non-English names; makes it harder if you want to hire non-Dutch speaking employees, distribute software ( code) internationally etc. I can't put my hands on the reference right now, but something like 99% of all software in the world is written purely for internal use and never gets distributed *at all*, let alone internationally. -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Question on tkinter event binding
Albert-Jan Roskam wrote: Meanwhile, I tinkered a bit more with the code. I used exec() to isolate the event handler function. It works and it's better, but I think it could be still better. I'm not so fond of eval() and exec(). They have their uses, but yes, it's best to avoid them unless you need them. Let's see if we can avoid them :) from Tkinter import * def createWidgets(veldnamen): root=Tk() termenlijst = {Naam: set([Bill Gates, Elvis Presley]), *Postcode: set([2600AA, 8000BB]), Adres: set([Street, Avenue])} handleDeletions = {} for veldnaam in veldnamen: labelWidget=Label(root, text=veldnaam, takefocus=False) labelWidget.grid() # tcl names must start with a lowercase letter tclName = veldnaam[0].lower() + veldnaam[1:] content = StringVar() entryWidget=Entry(root, name=tclName, textvariable=content) entryWidget.grid() exec(doHandleDeletion()) handleDeletions[entryWidget] = handleDeletion The classic solution for callbacks is to use lambda, but of course lambda is limited to a single expression and won't do the job here. So what you need is a factory function that returns a new function: handleDeletions[entryWidget] = make_deletion_handler() and the factory itself is defined something like this: def make_deletion_handler(): # Create a function. def handleDeletion(event, widget=entryWidget, root=root, termenlijst=termenlijst, content=content): actieveVenster = root.focus_get() actieveVensternaam = str(actieveVenster)[1:].capitalize() if actieveVensternaam.startswith(*): actieveVensternaam = *+actieveVensternaam[1:].capitalize() vensterinhoud = content.get().strip() print Name: %s -- Contents: %s \ % (actieveVensternaam, vensterinhoud) try: termenlijst[actieveVensternaam].remove(vensterinhoud) actieveVenster.delete(0, END) print Deleted term '%s' % vensterinhoud except KeyError: print No such term '%s' % vensterinhoud # And return it. return handleDeletion If you move the factory outside of your createWidgets function, you will need to explicitly pass arguments entryWidget, content, etc. to the factory. Otherwise you can nest the factory inside createWidgets, at it will pick the variables up automatically. Hope this helps, -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Question on tkinter event binding
Hi Steven, Awesome, I've got it working now! Here's the code: http://pastebin.com/BQhW8piD (I also pasted it below this message). I tried your approach before but I abandoned it because I made a mistake in lines 16 (pass None for event) and 22 (I didn't use the parameters of the outer function as the arguments of the inner function. Thanks a lot for putting me back on the right track!! It's really working cool now and I was able to remove some unnecessary code (and I added some bells and whistles ;-)) Cheers!! Albert-Jan import Tkinter, time, sys # To be used in conjunction with the AutocompleteEntry class: # http://tkinter.unpythonic.net/wiki/AutocompleteEntry def createWidgets(veldnamen, termenlijst): root=Tk() for veldnaam in veldnamen: labelWidget=Tkinter.Label(root, text=veldnaam, takefocus=False) labelWidget.grid() # tcl names must start with a lowercase letter tclName = veldnaam[0].lower() + veldnaam[1:] entryWidget=Tkinter.Entry(root, name=tclName, highlightcolor=yellow) entryWidget.grid() makeDeletionHandler(event=None, widget=entryWidget, root=root, termenlijst=termenlijst) def makeDeletionHandler(event, widget, root, termenlijst): def handleDeletion(event, widget=widget, root=root, termenlijst=termenlijst): vensternaam = str(widget)[1:].capitalize() if vensternaam.startswith(*): vensternaam = * + vensternaam[1:].capitalize() vensterinhoud = widget.get().strip() print Name: %s -- Contents: %s % (vensternaam, vensterinhoud) try: termenlijst[vensternaam].remove(vensterinhoud) widget.delete(0, END) widget.configure(bg = green) #print termenlijst print Deleted term '%s' % vensterinhoud except KeyError: print No such term '%s' % vensterinhoud pass finally: delay = 0.5 if sys.platform.lower().startswith(win): delay = delay * 1000 time.sleep(delay) # Windows: specify in ms!) widget.configure(bg = white) widget.bind(Shift-Delete, handleDeletion) return handleDeletion createWidgets(veldnamen = [Naam, *Postcode, Adres, *Organization name], termenlijst = {Naam: set([Bill Gates, Elvis Presley]), *Postcode: set([2600AA, 8000BB]), Adres: set([Street, Avenue]), *Organization name: set([CWI, MIT])}) ~~ All right, but apart from the sanitation, the medicine, education, wine, public order, irrigation, roads, a fresh water system, and public health, what have the Romans ever done for us? ~~ From: Steven D'Aprano st...@pearwood.info To: Python Mailing List tutor@python.org Sent: Sat, December 4, 2010 3:49:26 PM Subject: Re: [Tutor] Question on tkinter event binding Albert-Jan Roskam wrote: Meanwhile, I tinkered a bit more with the code. I used exec() to isolate the event handler function. It works and it's better, but I think it could be still better. I'm not so fond of eval() and exec(). They have their uses, but yes, it's best to avoid them unless you need them. Let's see if we can avoid them :) from Tkinter import * def createWidgets(veldnamen): root=Tk() termenlijst = {Naam: set([Bill Gates, Elvis Presley]), *Postcode: set([2600AA, 8000BB]), Adres: set([Street, Avenue])} handleDeletions = {} for veldnaam in veldnamen: labelWidget=Label(root, text=veldnaam, takefocus=False) labelWidget.grid() # tcl names must start with a lowercase letter tclName = veldnaam[0].lower() + veldnaam[1:] content = StringVar() entryWidget=Entry(root, name=tclName, textvariable=content) entryWidget.grid() exec(doHandleDeletion()) handleDeletions[entryWidget] = handleDeletion The classic solution for callbacks is to use lambda, but of course lambda is limited to a single expression and won't do the job here. So what you need is a factory function that returns a new function: handleDeletions[entryWidget] = make_deletion_handler() and the factory itself is defined something like this: def make_deletion_handler(): # Create a function. def handleDeletion(event, widget=entryWidget, root=root, termenlijst=termenlijst, content=content): actieveVenster = root.focus_get() actieveVensternaam = str(actieveVenster)[1:].capitalize() if actieveVensternaam.startswith(*): actieveVensternaam = *+actieveVensternaam[1:].capitalize() vensterinhoud
[Tutor] Question on tkinter event binding
Hi, I'm trying to make a small improvement on a data entry program and it is literally giving me a headache. I would appreciate your help or suggestions. The actual program uses Autocomplete entry widgets [1], which is a subclass of the Tkinter Entry widget. The sample code below uses a simple Entry widget, for the sake of simplicity. The autocompletions are recorded in a dictionary of the form {entry name: set(entries)}. The problem is that entries with typos cannot be deleted, so wrong autocomplete suggestions (Bbbilly Gates) are given until the end of time. My solution: I want to bind each entry widget to the Delete key, which makes it possible to remove the typo-entry from the set of entries. I am using an ' expanded event handler' [2] to do the event binding. The sample code below creates two entry widgets. The problem is that the entry contents is not retrieved correctly. If I fill the 2nd entry with some text, then hit 'Del' , it shows the content of the *first* entry. Also, I would like to isolate the event handler into its own function, not as a function within a function, but I'm not quite sure how. [1] http://tkinter.unpythonic.net/wiki/AutocompleteEntry [2] http://www.daniweb.com/code/snippet306072.html from Tkinter import * def createWidgets(veldnamen): root=Tk() termenlijst = {Naam: set([Bill Gates, Elvis Presley]), *Postcode: set([2600AA, 8000NN])} handleDels = {} for veldnaam in veldnamen: # tcl names must start with lowercase letter entryWidget=Entry(root, name=veldnaam[0].lower() + veldnaam[1:]) entryWidget.grid() def handleDel(event, widget=entryWidget, root=root, termenlijst=termenlijst): vensternaam = str(root.focus_get())[1:].capitalize() # ... and back to uppercase if vensternaam.startswith(*):# mandatory fields start with '*' in my program. vensternaam = * + vensternaam[1:].capitalize() vensterinhoud = entryWidget.get() print Naam, vensternaam # entry name print Inhoud, vensterinhoud # entry contents try: termenlijst[vensternaam].remove(vensterinhoud) # here's where the typo is removed except KeyError: pass # user tries to delete a term that doesn't exist in the termenlijst. handleDels[entryWidget] = handleDel # do all the bindings (is this where it goes wrong??) for entryWidget, handleDel in handleDels.iteritems(): entryWidget.bind(Delete, handleDel) print handleDels print termenlijst createWidgets([Naam, *Postcode]) Thanks again for having a look at this. Cheers!! Albert-Jan ~~ All right, but apart from the sanitation, the medicine, education, wine, public order, irrigation, roads, a fresh water system, and public health, what have the Romans ever done for us? ~~ ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Question on tkinter event binding
Aaahhh, got it! Peace! I did two things wrong: (1) I didn't use a tcl StringVar() to get the entry widget contents (2) I didn't consistently close the menus generated by previous attempts to run the program, which led to inconsistent results. I'll paste the working code below. It's partially in Dutch, but hey, so is Guido van Rossem. ;-) Even so, I'd be happy to hear suggestions for improvement or simplification. I'd love to chop the code up into smaller, more comprehensible bits. from Tkinter import * def createWidgets(veldnamen): root=Tk() termenlijst = {Naam: set([Bill Gates, Elvis Presley]), *Postcode: set([2600AA, 8000BB]), Adres: set([Street, Avenue])} handleDeletions = {} for veldnaam in veldnamen: labelWidget=Label(root, text=veldnaam, takefocus=False) labelWidget.grid() # tcl names must start with a lowercase letter tclName = veldnaam[0].lower() + veldnaam[1:] content = StringVar() entryWidget=Entry(root, name=tclName, textvariable=content) entryWidget.grid() def handleDeletion(event, widget=entryWidget, root=root, termenlijst=termenlijst,content=content): actieveVenster = root.focus_get() actieveVensternaam = str(actieveVenster)[1:].capitalize() if actieveVensternaam.startswith(*): actieveVensternaam = * + actieveVensternaam[1:].capitalize() vensterinhoud = content.get().strip() print Name: %s -- Contents: %s % (actieveVensternaam, vensterinhoud) try: termenlijst[actieveVensternaam].remove(vensterinhoud) actieveVenster.delete(0, END) print Deleted term '%s' % vensterinhoud except KeyError: print No such term '%s' % vensterinhoud pass handleDeletions[entryWidget] = handleDeletion for entryWidget, handleDeletion in handleDeletions.iteritems(): entryWidget.bind(Shift-Delete, handleDeletion) createWidgets([Naam, *Postcode, Adres]) Cheers!! Albert-Jan ~~ All right, but apart from the sanitation, the medicine, education, wine, public order, irrigation, roads, a fresh water system, and public health, what have the Romans ever done for us? ~~ From: Albert-Jan Roskam fo...@yahoo.com To: Python Mailing List tutor@python.org Sent: Fri, December 3, 2010 11:19:02 AM Subject: [Tutor] Question on tkinter event binding Hi, I'm trying to make a small improvement on a data entry program and it is literally giving me a headache. I would appreciate your help or suggestions. The actual program uses Autocomplete entry widgets [1], which is a subclass of the Tkinter Entry widget. The sample code below uses a simple Entry widget, for the sake of simplicity. The autocompletions are recorded in a dictionary of the form {entry name: set(entries)}. The problem is that entries with typos cannot be deleted, so wrong autocomplete suggestions (Bbbilly Gates) are given until the end of time. My solution: I want to bind each entry widget to the Delete key, which makes it possible to remove the typo-entry from the set of entries. I am using an ' expanded event handler' [2] to do the event binding. The sample code below creates two entry widgets. The problem is that the entry contents is not retrieved correctly. If I fill the 2nd entry with some text, then hit 'Del' , it shows the content of the *first* entry. Also, I would like to isolate the event handler into its own function, not as a function within a function, but I'm not quite sure how. [1] http://tkinter.unpythonic.net/wiki/AutocompleteEntry [2] http://www.daniweb.com/code/snippet306072.html from Tkinter import * def createWidgets(veldnamen): root=Tk() termenlijst = {Naam: set([Bill Gates, Elvis Presley]), *Postcode: set([2600AA, 8000NN])} handleDels = {} for veldnaam in veldnamen: # tcl names must start with lowercase letter entryWidget=Entry(root, name=veldnaam[0].lower() + veldnaam[1:]) entryWidget.grid() def handleDel(event, widget=entryWidget, root=root, termenlijst=termenlijst): vensternaam = str(root.focus_get())[1:].capitalize() # ... and back to uppercase if vensternaam.startswith(*):# mandatory fields start with '*' in my program. vensternaam = * + vensternaam[1:].capitalize() vensterinhoud = entryWidget.get() print Naam, vensternaam # entry name print Inhoud, vensterinhoud # entry contents try: termenlijst[vensternaam].remove(vensterinhoud) # here's where the typo is removed except KeyError: pass # user tries to delete a term
Re: [Tutor] Question on tkinter event binding
On Fri, 3 Dec 2010, Albert-Jan Roskam wrote: I'm trying to make a small improvement on a data entry program and it is literally giving me a headache. Followed shortly thereafter with: On Fri, 3 Dec 2010, Albert-Jan Roskam wrote: Aaahhh, got it! Peace! ... I'll paste the working code below. It's partially in Dutch, but hey, so is Guido van Rossem. ;-) Once again proving the Zen of Python: import this The Zen of Python, by Tim Peters . . . There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor