views:

463

answers:

2

I'm writing a small utility in Python that does some pattern matching of text. Text that matches the pattern the user has entered gets highlighted yellow. I'm achieving this using a Tkinter Text widget, and setting up a tag on the textbox named "match" that gives any text with the tag name "match" a yellow background. This all looks nice, except when I go to highlight the text using the mouse (e.g. when wanting to copy/paste). When I highlight the text with the mouse, any of the tagged text that already has a yellow background retains its yellow background, even after being highlighted. This means you can't properly read the text when it's been highlighted by the mouse, as the white text (text goes white when highlighted by mouse) on a yellow background provides bad contrast.

What I would like to happen is that when I highlight the text in the Text widget using the mouse, all of the text gets the standard blue background color/white text color that you'd normally get on a Windows machine when highlighting a section of text.

Here's a quick code snippet to demonstrate what I mean:

from Tkinter import *

root = Tk()

w = Text(root)
w.tag_config("match",background="yellow")
w.config(highlightbackground="red")
w.pack()
w.insert(INSERT,"some non-matching text.")
w.insert(INSERT,"some matching text.","match")

root.mainloop()

If you run this, and then highlight all of the text in the Text widget, you'll see that the text with the yellow background becomes very hard to read. Note that in the code snippet above I've tried changing the highlight background color using:

w.config(highlightbackground="red")

But this hasn't worked.

A: 

I think you need to set selectbackground, not highlightbackground which means something completely different (the bg color for the "highlight rectangle" drawn around a widget when it gets focus). However, I believe the sel pseudo-tag (representing the selection, which is what I think you're calling "the highlight") is "below" user-created tags such as your match; if so, then the bg color for the user-created tag would show, not the bg color for the sel pseudo-tag (aka selectbackground).

With Tk 8.5 you could remedy that by binding to the <Selection> pseudo-event a function that places an appropriately colored user tag "on top" of pseudo-tag sel; however, there is no such event in Tk 8.4, which is what most likely you're using today. TK's docs say that 8.5 comes with Python 3.1 on the ActiveState distribution of Python for Windows; unfortunately there are only "TODO" placeholders regarding other platforms or other versions of Python -- I don't know how to best obtain Tk 8.5 for the specific platform(s) and python version(s) of your interest.

Alex Martelli
while what you write is technically correct, it doesn't actually solve the problem and implies that the problem can only be solved with a specific version of Tk.
Bryan Oakley
A: 

Tags have priority. Tags with a high priority have preference over those that have a lower priority. When you select a range of text it is given the tag "sel". You simply need to raise the priority of the "sel" tag to be above the priority of your "match" tag:

w.tag_raise("sel")

Alex Martelli writes in the comments "it will do the OP absoluely [sic] no good if he sets highlightbackground instead of selectbackground" but that is incorrect. While he is correct that setting highlightbackground has nothing to do with the selection, it has no bearing on this solution.

Raising the priority of the "sel" tag works with the code in the original question, with or without the addition of the code that sets highlightbackground.

For more information on the text widget check out the text widget tutorial on tkdocs.com. It has code examples in Tcl, Python, Ruby and Perl.

Bryan Oakley
While what you write is technically correct, it will do the OP absoluely no good if he sets highlightbackground instead of selectbackground (basically, you need this answer _plus_ the first paragraph of mine;-).
Alex Martelli
You are incorrect. My solution solves his problem with or without configuring the highlightbackground or the selectbackground. I think you down-voted me simply because I down-voted you. The difference is, my solution works your non-solution doesn't.
Bryan Oakley
I have to concur with Bryan - using w.tag_raise("sel") is all that was required for the example I provided in the original question.
Bryce Thomas