Prev: Solved: TypeError: startView() takes exactly 1 argument (3 given)
Next: How to Suppress Interactive Assignment to "_"
From: Dave McCormick on 31 Dec 2009 16:41 Thanks John and Lie, This is supposed to color the word "red" red, "blue" blue, "green" green, etc... The idea is say for a database front end, the search words will be highlighted or colored when the query is returned. Another thing I want to try is a Program editor, something like IDLE. The program editor will be for Pic Basic Pro, (I mainly work with PIC CHIPS). Yes there is a couple of good editors for PBP in Windows but not Linux. Yup, I have a long ways to go. Got to start some place :) I was doing the grid because that is how the example I read dealing with scrollbars worked. I stripped the scrollbar part out while working on the colors. So I need to look at the pack() method more. I will work on this more tonight and I will not look at your code before I get something working. Thanks again, Dave John Posner wrote: > On Thu, 31 Dec 2009 10:24:44 -0500, Dave McCormick <mackrackit(a)gmail.com> > wrote: > >> John, >> >> Thank you for the tips. >> I was changing the line-column index to a FLOAT because the search >> would return the starting position (pos) of the string, then by >> making it a FLOAT and adding the string length I was able to get the >> end position. >> If "red" was on line 1 column 0.. >> Tbox.tag_add("red", pos, float(pos)+.03) >> = >> Tbox.tag_add("red", 1.0, 1.3) >> It was all I could come up with. > > Yup, Dave, I've dug this kind of hole for myself many times! > >> >> You have convinced me about the re.finditer for this, I think... >> Still in the prototyping mode: >> >> def get_position(event): >> pos = Tbox.get(1.0, END) >> match = [ matchobj.span() for matchobj in >> re.finditer("red", pos) ] >> print "match ",match #debug to shell > > Notes: > > * Variable "pos" should be "text" or "complete_text" or something > similar. > > * The first argument to the get() function must be a string: > > wrong ... complete_text = Tbox.get(1.0, END) > right ... complete_text = Tbox.get("1.0", END) > > But there's a more important problem. Is this function supposed to > handle *one* word to be colored red, or *all the words* to be colored > red? Here's what you want to do on each user keystroke: > > 1. Use get() to place the entire contents of the Text widget in a > variable, say "complete_text". > > 2. Use re.finditer() to generate START,END pairs for the > substrings to > be colored red. You might find it easier to create a list from the > iterator, though it isn't really necessary: > > start_end_pairs = list(re.finditer("red", complete_text)) > > 3. Loop over the START,END pairs in this list. In each loop, use > tag_add() to tag one of the substrings. > > [OOPS: I apologize if my suggestion in the previous post misled you. I > described the output of finditer() as "a list of (start,end) pairs for > an invocation of Text.tag_add()". I should have said "a list of > (start,end) pairs, *WHICH CAN BE LOOPED OVER, FOR A SERIES OF > INVOCATIONS* of Text.tag_add()".] > > Note that the 3 steps above only handle the color red. So you want to > place these steps in a function, then call the function for each color: > > insert_color_markup(text, "red") > insert_color_markup(text, "green") > insert_color_markup(text, "blue") > > For each call, pass in the contents of complete_text as the first > argument. > > So the function-call hierarchy would be: > > get_position() <--- invoked on each keystroke > insert_color_markup() <--- called once for each color > get() then finditer() then loop-driven calls to tag_add() > > I hope that makes sense to you! > > >> Gives all of START,END pairs just fine. It is the last hint about >> line-column indexes that I am have problems with. All of the >> documentation I can find about "text.tag_add()" uses line-column for >> coordinates. > > Lie Ryan has already pointed you to clarifying documentation. Be sure > to bookmark http://infohost.nmt.edu/tcc/help/pubs/tkinter/ in your Web > browser! > >> If I count characters from the beginning how do I know what line the >> text is on? Would you mind making your last hint a bit stronger... > > The point is that *you don't need to*. Handling the text as a simple > sequence of characters is much simpler than worrying about line/column > pairs. (If you were using a different shade of red on different lines, > you *would* need to worry about line/column pairs.) > > One more suggestion, which I forgot to make in the previous round. > Your code includes this: > > Tbox.grid(column=0, row=0, sticky=(N+W+E+S)) > root.grid_columnconfigure(0, weight=1) > root.grid_rowconfigure(0, weight=1) > > You're working too hard here. This is sufficient: > > Tbox.pack() > > Keep at it, Dave. I've posted a complete solution at > http://cl1p.net/jjp_dynamic_text_color/. But I suggest that you put in > a couple of more hours of coding before peeking at it. > > Best, > John
From: Cousin Stanley on 1 Jan 2010 21:01 > John Posner wrote .... > .... > I've posted a complete solution .... > > http://cl1p.net/jjp_dynamic_text_color/. John .... Thanks for posting your solution to Dave McCormick's query about colorizing text .... I was not familiar with the re.finditer method for searching strings or with using tags in Tkinter Text widgets to change text attributes .... Instead of binding the Text widget to <KeyRelease> events to call the colorizer on each key-stroke, I used a button callback .... http://cl1p.net/cs_static_text_color This provides a static one-shot colorization after all of the text is entered and should save a few cpu cycles although it's not as nifty as the dynamic process .... I used a dictionary instead of a list for position data and also added a { term : color } dictionary so that words other than color names can be hi-lighted .... -- Stanley C. Kitching Human Being Phoenix, Arizona
From: Dave McCormick on 2 Jan 2010 13:47 WooHoo!!! I got it!!! Yup, I am sure it can be optimized but it works!!! John, I have to admit that I spent several hours working on this before I looked at your example, then I spent another several hours getting this far. Would never have gotten it with out you help. Thanks!!! Also reading the thread "Significant whitespace" helped. I had an indent problem in a FOR loop. This is a whole lot different than the MCU programming I do in ASM or BASIC, starting to make sense though. Thanks again for all the help and putting up with folks like me, Dave Here is what I can up with. ####### from Tkinter import * import re redList = "red dog".split() blueList = "blue ball".split() greenList = "green grass".split() def get_position(event): complete = Tbox.get("1.0", END) ####RED######## for word in redList: new_Rword(complete, word) def new_Rword(complete, word): Tbox.tag_remove(word, "1.0", END) for matchobj in re.finditer(word, complete): start,end = matchobj.span() Tbox.tag_add("red", "1.0 + %d chars" % start,"1.0 + %d chars" % end) Tbox.tag_config("red", foreground="red") ####BLUE####### for word in blueList: new_Bword(complete, word) def new_Bword(complete, word): Tbox.tag_remove(word, "1.0", END) for matchobj in re.finditer(word, complete): start,end = matchobj.span() Tbox.tag_add("blue", "1.0 + %d chars" % start,"1.0 + %d chars" % end) Tbox.tag_config("blue", foreground="blue") ####GREEN####### for word in greenList: new_Gword(complete, word) def new_Gword(complete, word): Tbox.tag_remove(word, "1.0", END) for matchobj in re.finditer(word, complete): start,end = matchobj.span() Tbox.tag_add("green", "1.0 + %d chars" % start,"1.0 + %d chars" % end) Tbox.tag_config("green", foreground="green") root = Tk() Tbox = Text(root, width=40, height=15, wrap=CHAR, font="Times 14 bold", bg="#dddddd") Tbox.pack() Tbox.bind("<KeyRelease>", get_position) Tbox.focus() root.mainloop() John Posner wrote: > On Thu, 31 Dec 2009 10:24:44 -0500, Dave McCormick <mackrackit(a)gmail.com> > wrote: > >> John, >> >> Thank you for the tips. >> I was changing the line-column index to a FLOAT because the search >> would return the starting position (pos) of the string, then by >> making it a FLOAT and adding the string length I was able to get the >> end position. >> If "red" was on line 1 column 0.. >> Tbox.tag_add("red", pos, float(pos)+.03) >> = >> Tbox.tag_add("red", 1.0, 1.3) >> It was all I could come up with. > > Yup, Dave, I've dug this kind of hole for myself many times! > >> >> You have convinced me about the re.finditer for this, I think... >> Still in the prototyping mode: >> >> def get_position(event): >> pos = Tbox.get(1.0, END) >> match = [ matchobj.span() for matchobj in >> re.finditer("red", pos) ] >> print "match ",match #debug to shell > > Notes: > > * Variable "pos" should be "text" or "complete_text" or something > similar. > > * The first argument to the get() function must be a string: > > wrong ... complete_text = Tbox.get(1.0, END) > right ... complete_text = Tbox.get("1.0", END) > > But there's a more important problem. Is this function supposed to > handle *one* word to be colored red, or *all the words* to be colored > red? Here's what you want to do on each user keystroke: > > 1. Use get() to place the entire contents of the Text widget in a > variable, say "complete_text". > > 2. Use re.finditer() to generate START,END pairs for the > substrings to > be colored red. You might find it easier to create a list from the > iterator, though it isn't really necessary: > > start_end_pairs = list(re.finditer("red", complete_text)) > > 3. Loop over the START,END pairs in this list. In each loop, use > tag_add() to tag one of the substrings. > > [OOPS: I apologize if my suggestion in the previous post misled you. I > described the output of finditer() as "a list of (start,end) pairs for > an invocation of Text.tag_add()". I should have said "a list of > (start,end) pairs, *WHICH CAN BE LOOPED OVER, FOR A SERIES OF > INVOCATIONS* of Text.tag_add()".] > > Note that the 3 steps above only handle the color red. So you want to > place these steps in a function, then call the function for each color: > > insert_color_markup(text, "red") > insert_color_markup(text, "green") > insert_color_markup(text, "blue") > > For each call, pass in the contents of complete_text as the first > argument. > > So the function-call hierarchy would be: > > get_position() <--- invoked on each keystroke > insert_color_markup() <--- called once for each color > get() then finditer() then loop-driven calls to tag_add() > > I hope that makes sense to you! > > >> Gives all of START,END pairs just fine. It is the last hint about >> line-column indexes that I am have problems with. All of the >> documentation I can find about "text.tag_add()" uses line-column for >> coordinates. > > Lie Ryan has already pointed you to clarifying documentation. Be sure > to bookmark http://infohost.nmt.edu/tcc/help/pubs/tkinter/ in your Web > browser! > >> If I count characters from the beginning how do I know what line the >> text is on? Would you mind making your last hint a bit stronger... > > The point is that *you don't need to*. Handling the text as a simple > sequence of characters is much simpler than worrying about line/column > pairs. (If you were using a different shade of red on different lines, > you *would* need to worry about line/column pairs.) > > One more suggestion, which I forgot to make in the previous round. > Your code includes this: > > Tbox.grid(column=0, row=0, sticky=(N+W+E+S)) > root.grid_columnconfigure(0, weight=1) > root.grid_rowconfigure(0, weight=1) > > You're working too hard here. This is sufficient: > > Tbox.pack() > > Keep at it, Dave. I've posted a complete solution at > http://cl1p.net/jjp_dynamic_text_color/. But I suggest that you put in > a couple of more hours of coding before peeking at it. > > Best, > John
From: John Posner on 2 Jan 2010 20:52 On Sat, Jan 2, 2010 at 1:47 PM, Dave McCormick wrote: > WooHoo!!! > I got it!!! Yup, I am sure it can be optimized but it works!!! Dave, please ignore a couple of my bogus complaints in the previous message: ... you call function new_Rword() before you define it ... this version also has the advantage of defining each function just once, instead of multiple times on each keystroke But I stand by my overall statement that the program didn't work for me, and that rearranging the lines produces a working program. -John
From: John Posner on 2 Jan 2010 20:38 On Sat, Jan 2, 2010 at 1:47 PM, Dave McCormick wrote: > WooHoo!!! > I got it!!! Yup, I am sure it can be optimized but it works!!! Hmmm ... it doesn't work for me ... <snip> ####RED######## > for word in redList: > new_Rword(complete, word) def new_Rword(complete, word): > Tbox.tag_remove(word, "1.0", END) > for matchobj in re.finditer(word, complete): > start,end = matchobj.span() Tbox.tag_add("red", > "1.0 + %d chars" % start,"1.0 + %d chars" % end) > Tbox.tag_config("red", foreground="red") How *could* this work, Dave, since you call function new_Rword() before you define it? I rearranged the statements in your program, and it now works for me: #--------------------------------------------- from Tkinter import * import re redList = "red dog".split() blueList = "blue ball".split() greenList = "green grass".split() def get_position(event): complete = Tbox.get("1.0", END) for word in redList: new_Rword(complete, word) for word in blueList: new_Bword(complete, word) for word in greenList: new_Gword(complete, word) def new_Rword(complete, word): Tbox.tag_remove(word, "1.0", END) for matchobj in re.finditer(word, complete): start,end = matchobj.span() Tbox.tag_add("red", "1.0 + %d chars" % start,"1.0 + %d chars" % end) def new_Bword(complete, word): Tbox.tag_remove(word, "1.0", END) for matchobj in re.finditer(word, complete): start,end = matchobj.span() Tbox.tag_add("blue", "1.0 + %d chars" % start,"1.0 + %d chars" % end) def new_Gword(complete, word): Tbox.tag_remove(word, "1.0", END) for matchobj in re.finditer(word, complete): start,end = matchobj.span() Tbox.tag_add("green", "1.0 + %d chars" % start,"1.0 + %d chars" % end) root = Tk() Tbox = Text(root, width=40, height=15, wrap=CHAR, font="Times 14 bold", bg="#dddddd") Tbox.tag_config("red", foreground="red") Tbox.tag_config("blue", foreground="blue") Tbox.tag_config("green", foreground="green") Tbox.pack() Tbox.bind("<KeyRelease>", get_position) Tbox.focus() root.mainloop() #--------------------------------------------- This version also has the advantage of defining each function just once, instead of multiple times on each keystroke! Still to-do: * rename get_position() to get_complete_text() * replace new_Rword(), new_Bword(), and new_Gword() with a single function that has an extra parameter, "color". Keep at it! -John
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 4 5 Prev: Solved: TypeError: startView() takes exactly 1 argument (3 given) Next: How to Suppress Interactive Assignment to "_" |