4

I get the number of lines of a tkinter Text widget like this:

import Tkinter as Tk

def countlines(event):
    print float(event.widget.index(Tk.END))-1 
    print event.widget.get("1.0", Tk.END).count("\n")

root = Tk.Tk()
root.geometry("200x200")
a = Tk.Text(root)
a.pack()
a.bind("<Key>", countlines)

root.mainloop()

Only problem : when you hit <Return>, the count of lines doesn't increase. You need to add some futher text in order that count of lines increases.

How to make that < Return > key increases the count of lines ?

Basj
  • 41,386
  • 99
  • 383
  • 673

1 Answers1

4

Don't get all the text and then count, just get the index of the last-minus-one character with index("end-1c") and then do some string manipulation to get the line number.

As for why the number doesn't increase, it's because your binding happens before the return key is inserted. For your simple test you can work around this by binding on <KeyRelease>, since the character is inserted on the press.

import Tkinter as Tk

def countlines(event):
    (line, c) = map(int, event.widget.index("end-1c").split("."))
    print line, c

root = Tk.Tk()
root.geometry("200x200")
a = Tk.Text(root)
a.pack()
a.bind("<KeyRelease>", countlines)

root.mainloop()

If you need to print the value on the key press, you'll have to use an advanced feature called "bindtags". Bindtags are covered briefly in an answer to this question: Basic query regarding bindtags in tkinter. In short, you have to create a custom bindtag that appears after the class bindtag, so that your binding happens after the class binding.

Here's how to modify your program to use bindtags:

import Tkinter as Tk

def countlines(event):
    (line, c) = map(int, event.widget.index("end-1c").split("."))
    print line, c

root = Tk.Tk()
root.geometry("200x200")
a = Tk.Text(root)
a.pack()
bindtags = list(a.bindtags())
bindtags.insert(2, "custom")
a.bindtags(tuple(bindtags))
a.bind_class("custom", "<Key>", countlines)

root.mainloop()
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • Thanks! Isn't it possible to get the count when the Key is **pressed** (and not *released*, because sometimes you hold the key for a long time) ? – Basj Dec 13 '13 at 11:50
  • @Basj: If you hold the key long enough it will start repeating and adding more than one character -- so it seems obvious you would want to wait until it was released. – martineau Dec 13 '13 at 12:00
  • No @martineau because I need to update display in realtime (it depends on realtime count of lines) – Basj Dec 13 '13 at 12:03
  • Thanks @BryanOakley ! It works ! (but I don't understand the index("end-1c") ;) what is this "end-1c" ? and why split with "." ? why this char ?) – Basj Dec 13 '13 at 12:08
  • 1
    The text widget always adds an extra newline at the end, which you don't want to count. That's why "end-1c". We split on "." because `.index()` returns a string of the form "line.column" (eg: `1.0`, `2.14`, etc) – Bryan Oakley Dec 13 '13 at 12:15