Help with text editing!

Eric Brunel eric.brunel at pragmadev.com
Fri Apr 11 05:48:13 EDT 2003


jinal jhaveri wrote:
> Dear All
> 
> 
> I have written following code for the file open wizard of my editor
> 
> which sets the text.
> where text arg is one read from a file.
> 
> 
>  def setAllText(self,text):
>                 self.text.delete('1.0',END)
>                 self.text.insert(END,text)
>                 self.text.mark_set(INSERT,'1.0')
>                 self.text.see(INSERT)
> 
> Now I want two things to be donw
> 
> 1) I want to display this text such that alternate rows have same color and alternate columns have same color
> 
> for eg. 
> assume columsn are alternatively in blue and green.
> 
> BGBGBGBGBGBGBGBGBGBGBGBGBGBGBGBGBGBGBGB (ASSUMING THIS IS BLACK)
> WGWGWGWGWGWGWGWGWGWGWGWGWGWGWGWGWGWGWGW (ASSUMING THIS IS WHITE)
> 
> Can anyone give me an idea how do I modify this text to do that?
> 
> 2) Instead of allowing the edit for the whole text I have entered, I want editing possible only line per line basis.
> for eg. 
> 
> name1 JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
> name2 IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
> name3 KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
> 
> so when I select this text , it should allow me to edit only the line  (only line not even name1,name2 etc) on which I do double click and it shouldn't allow me to edit the whole text.
> 
> 
> I will highly appreciate if someone can give me hints on how to go about

Let me answer first to the second point: you won't be able to do that with a 
single Text widget. The Text widget is intended to display a _text_, which will 
be modifiable as a whole.

So my advice would be to use as many text widgets as there are lines to modify. 
And do not include the name in the text, but put it outside in a label. The next 
thing is that you may be annoyed by the fact that Text widgets are natively 
multi-line, so a press on Return will insert a new line. You can change that by 
explicitely doing a binding on the Return key. My first idea was to use entries 
(much easier to use for what you want to do) but your first point seem to 
indicate that you want your texts to have several colours, and entries can't do 
that.

Here is an example:

-------------------------------------------
from Tkinter import *

class SingleLineText(Text):

   def __init__(self, *args, **options):
     ## Height = 1 line + explicitely ignore the 'wrap' option
     options['height'] = 1
     options['wrap'] = 'none'
     apply(Text.__init__, (self,) + args, options)
     ## Ignore binding for 'Return' key
     self.bind('<Return>', lambda evt: 'break')

root = Tk()
for i in range(20):
   name = 'name%s' % i
   l = Label(root, text=name)
   l.grid(row=i, column=0, sticky='w')
   t = SingleLineText(root, width=24, bd=0, bg='white')
   t.grid(row=i, column=1, sticky='w')
root.mainloop()
-------------------------------------------

Not very cute, but you get the idea.

To do what I can understand for your first point, you can use the following 
sub-class of SingleTextLine:

--------------------------------------------
class AltColouredSingleLineText(SingleLineText):

   def __init__(self, *args, **options):
     ## Get specific options for this widget
     colour1, colour2 = 'blue', 'green'   # Whatever...
     if options.has_key('colour1'):
       colour1 = options['colour1']
       del options['colour1']
     if options.has_key('colour2'):
       colour2 = options['colour2']
       del options['colour2']
     ## Super-init
     apply(SingleLineText.__init__, (self,) + args, options)
     ## Create/configure tags in text
     self.tag_configure('COLOUR1', foreground=colour1)
     self.tag_configure('COLOUR2', foreground=colour2)
     ## Binding on any key release to display the colours
     self.bind('<KeyRelease>', self.__updateColours)

   def __updateColours(self, evt):
     ## Remove former tags
     self.tag_remove('COLOUR1', 1.0, END)
     self.tag_remove('COLOUR2', 1.0, END)
     ## Get text length
     textLen = len(self.get(1.0, '1.end'))
     ## Browse all text to update colours
     for i in range(0, textLen, 2):
       self.tag_add('COLOUR1', '1.%s' % i)
       self.tag_add('COLOUR2', '1.%s' % (i+1))
--------------------------------------------

Then use a line like:

t = AltColouredSingleLineText(root, width=24, bd=0, bg='white',
                               colour1='red', colour2='blue')

instead of the line:

t = SingleLineText(root, width=24, bd=0, bg='white')

in the code above.

For more information on what you can do with the Text widget, please refer to:
http://www.pythonware.com/library/tkinter/introduction/text.htm

HTH
-- 
- Eric Brunel <eric.brunel at pragmadev.com> -
PragmaDev : Real Time Software Development Tools - http://www.pragmadev.com





More information about the Python-list mailing list