简体   繁体   中英

What's the most efficient way to get a Tkinter Text widget's total display lines after the insert?

Is there a more efficient way to get the total number of display lines (not just visible ones) that are left in a tkinter Text widget after the text insert than with this makeshift function I came up with (in Python 3.4.2):

def get_display_lines():
    #Gets the total number of display lines after the text insert in the current tab (not just those on-screen, though).
    myTextWidget.mark_set("dlines", INSERT)
    count=0
    while 1:
        if myTextWidget.compare("dlines", ">=", "end-1c linestart"):
            break
        else:
            myTextWidget.mark_set("dlines", "dlines + 1 display line")
            count+=1
    return count

Anyway, this code works, but it's rather inefficient. I'm using it to calculate the time left to autoscroll through the remainder document. The inefficiency causes problems when moving the text insert with the arrow keys (which calls this function so as to show a current accurate time). It makes moving the insert much slower, and slower to update, and can even crash/freeze it.

I know there are much more efficient ways to get the total number of lines in a Text widget. However, I need the display lines, because reading with autoscroll is usually done with the wordwrap on.

My autoscroll feature goes down from the insert a user-chosen number of lines every so many seconds (which number of second is also chosen by the user). It's not done through the scrollbars.

If you only care about the time to scroll through the document, and if the data doesn't change as you're scrolling (ie: new lines aren't being added) you can simply calculate how many pixels the document takes up (you only have to do this once), and where you currently are in the document. That will tell you how many pixels are left. From that you should be able to calculate an approximation of how much time it will take.

You can get the total number of pixels used in the text widget with myTextWidget.count("1.0", "end", "ypixels" . You can then get the y coordinate of the current line with myTextWidget.dlineinfo("insert") . From those two numbers you can compute a percentage of how far the insertion point is from the end of the widget.

Okay, I found an answer (and yes, this is purposefully an answer; it's not part of my question).

The following code will much more efficiently give the number of display lines left after the text insert:

def get_display_lines(start="insert", end="end-1c")
    try:
        count=myTextWidget.count(start, end, "displaylines")[0]
    except TypeError:
        count=0
    return count

Although this is much more efficient, it is still not totally efficient and will have trouble with large files (if you're using the arrow keys a lot during autoscroll). The count() method returns a tuple; hence, the zero index. Because this does not always contain a number (like when the insert is at the end of the document), that is why I use a try/except block (although you could do this lots of other ways; however you please).

Because this is not efficient for large files, you might just get the current lines left once, save them, and increment/decrement this variable when updating the status (granted, that will require editing a bunch of functions, but it is more efficient). You'll need to update the total during edits, though (fortunately, that is less common while autoscrolling).

Because messing around with a lot of other functions is a lot of overhead, and increases the complexity of editing the code, I suggest just only having it update on the autoscroll intervals, rather than when the user manually moves the cursor. Also, to increase efficiency, don't have it calculate the lines left (let alone the time left from that) in the statusbar update method, but only calculate it in a saved variable from the method called by the timer, and just print the variable in the statusbar.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM