JohnT
JohnT

Reputation: 151

Correct way to set scrollbar position in python tkinter

I am making a basic text editor and I am saving the scroll position in a file on closing the program. Then when opening the program it will read the scroll position from the file and update it so you can continue where you left off.

I can get the position fine from scrolledtext.yview() which returns a tuple with e.g. (0.42, 0.75)

But I cannot figure out how to change the scroll position. I have tried scrolledtext.vbar.set(0.42, 0.75) to try and update it but that doesn't work as in it doesn't do anything and gives no errors. I have also tried scrolledtext.yview(0.42, 0.75) but it says TclError: bad option "0.42": must be moveto or scroll so if anyone knows how to update it that would be greatly appreciated, cheers.

Edit(Code):

import tkinter as tk

root = tk.Tk()
Frame = frame(root)
Frame.pack()
textbox = ScrolledText(Frame)
textbox.pack()
textbox.yview()  #this is saved to file, produces tuple of e.g. (0.42, 0.75)
textbox.vbar.set(0.3, 0.7)  #this doesn't produce any errors but doesn't change the scroll position 
textbox.yview(0.3, 0.7)  #this is also something i have tried but produces the error _tkinter.TclError: bad option "0.4243827160493827": must be moveto or scroll

root.mainloop()

Upvotes: 5

Views: 11961

Answers (2)

Valeriy Chepelev
Valeriy Chepelev

Reputation: 26

In case of widgets update with change bbox sizes, i use a followed snippet to keep scroll position:

#before repaint store vsb position caclulated in pixels from top
bbox = canvas.bbox(ALL)
self.mem_vsb_pos = canvas.yview()[0] * (bbox[3] - bbox[1])

#after repaint (back calculation):
bbox = canvas.bbox(ALL)
canvas.yview_moveto(self.do_vsb_pos / (bbox[3]-bbox[1]))

#before repaint - if need repaint from top
self.mem_vsb_pos = 0.0

Upvotes: 0

Bryan Oakley
Bryan Oakley

Reputation: 385860

You can't expect the saved yview to work in all cases. If the file has been edited, the proportions could be all wrong.

The tuple you get from yview represents the fraction visible at the top and the fraction visible at the bottom. You can call yview_moveto to set the position at the top, and then let tkinter take care of the fraction at the bottom.

For example, if the yview you've saved is (0.42, 0.75), then you just need to call yview_moveto('0.42'). This will cause the view to be adjusted so that the given offset is at the top of the window.

Upvotes: 7

Related Questions