Dynamic text color
Dave McCormick
mackrackit at gmail.com
Thu Dec 31 10:24:44 EST 2009
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.
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
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.
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...
Thanks again!
Dave
John Posner wrote:
> On Wed, 30 Dec 2009 12:58:06 -0500, Dave McCormick
> <mackrackit at gmail.com> wrote:
>
>> Hi All,
>>
>> I am new to Python and the list so I hope I am posting this
>> correctly...
>>
>> I am working on a way to have text automatically formated in a
>> Tkiniter Text widget and would like some input on my code.
>> Currently I am using Python 2.5 because the server I use has that
>> installed. Tkinter is tk8.4.
>>
>> Most of the time when I type red, blue, or green the code works as
>> expected. When I copy paste text into the widget the last line is
>> parsed with part of the previous lines
>> So I guess the problem is in the "looping"?
>>
>> Here is my code:
>> from Tkinter import *
>> root = Tk()
>> def get_position(event):
>> start = 1.0
>
> A couple of problems here: you define "start", but then never use it.
> Worse, it looks like you don't understand that a line-column index
> into a Tkinter Text widget is a STRING, not a FLOAT.
>
>
>> while 1: pos = Tbox.search("red",END,backwards=TRUE)
>
> I suggest that you use Tbox.get() instead of Tbox.search(), and then
> use Python's more powerful text-search tools. More on this below.
>
>
>> if not pos:
>> break
>> red = pos + "-1c"
>> Tbox.tag_add("red", pos, float(pos)+.03)
>> Tbox.tag_config("red", foreground="red")
>
> You don't want to define the "red" tag every time get_position() is
> executed -- that is, every time the user presses a key. Define the
> red/green/blue tags just once, right after you create the Text widget.
>
>
>> pos = Tbox.search("blue",END,backwards=TRUE)
>> if not pos:
>> break
>> blue = pos + "-1c"
>> Tbox.tag_add("blue", pos, float(pos)+.04)
>> Tbox.tag_config("blue", foreground="blue")
>>
>> pos = Tbox.search("green",END,backwards=TRUE)
>> if not pos:
>> break
>> green = pos + "-1c"
>> Tbox.tag_add("green", pos, float(pos)+.05)
>> Tbox.tag_config("green", foreground="green")
>
> The previous 6 lines are almost identical to the 6 lines that precede
> them. This is fine for prototyping, but when you find yourself writing
> code like this, think about using a loop or a parameterized function
> call. For example, you might write this function:
>
> def insert_color_markup(color):
> ...
>
> ... and then call it as many times as you need to:
>
> insert_color_markup("red")
> insert_color_markup("green")
> insert_color_markup("blue")
>
> Now, about those text-search tools: the "re" (regular expression)
> module include the function "finditer". This is a real power tool,
> combining regular expressions and Python iterators -- both of which
> can be intimidating to newcomers. But it's just what you want, IMHO. I
> hope the following annotated IDLE transcript convinces you:
>
> Python 2.6.4 (r264:75708, Oct 26 2009, 08:23:19) [MSC v.1500 32 bit
> (Intel)] on win32
>>>> import re
>
>>>> text = """The red ball is red, not green. On other other
> ... hand, the green ball has both red and blue highlights.
> ... Thank you.
> ... """
>
>>>> re.finditer("red", text)
> <callable-iterator object at 0x00CC46D0>
>
> ... not too exciting, but this is better:
>
>>>> list(re.finditer("red", text))
> [<_sre.SRE_Match object at 0x00C01F70>, <_sre.SRE_Match object at
> 0x00C06E20>, <_sre.
> SRE_Match object at 0x00C06E58>]
>
> ... this list indicates that we got three hits on the word "red"
>
>>>> [ matchobj.span() for matchobj in re.finditer("red", text) ]
> [(4, 7), (16, 19), (77, 80)]
>
> ... paydirt: a list of (start,end) pairs for an invocation of
> Text.tag_add()
>
> One more hint: forget about the line-column indexes into the contexts
> of a Text widget. Just count characters from the beginning, e.g.:
>
> "1.0 + %d chars" % start_position
>
>> break
>>
>> Tbox = Text(root,width=40, height=15, wrap=CHAR)
>> Tbox.grid(column=0, row=0, sticky=(N+W+E+S))
>> root.grid_columnconfigure(0, weight=1)
>> root.grid_rowconfigure(0, weight=1)
>> Tbox.bind("<KeyRelease>", get_position)
>> Tbox.focus()
>> root.mainloop()
>>
>> Thank you,
>> Dave
>
> I hope this set of hints is helpful, and not too disjointed, terse, or
> cryptic. I think this is a cute little app!
>
> -John
More information about the Python-list
mailing list