Вобщем ИМХО вы выбрали неудачный инструмент для решения вашей задачи. Tkinter весьма убог в плане возможностей по сравнению с тем же PyQt/PySide или WxPython.
Все что мы можем, это получить индекс текущей строки, и координаты начала строки/любого символа.
Соответвенно алгоритм прост, если У-координата строки слева больше У-координаты строки справа, нудно прокрутить левую сторону вверх, иначе прокрутить вниз.Вобщето можно(нужно) также контролировать и положения конца строки(на случай если “абзац” не будет полностью вмещаться в видимую область) и в случае чего ровняться по ней. Иначе начало строки уйдет вверх, TextWidget.bbox вернет None, и правая сторона не будет пролистываться.
А можно сравнивать координаты среднего символа в строке, и тогда оно будет равняться на середину, ну както так.
Примерный код, привел ниже, он конечно еще сырой и требует доработки, но думаю общий смысл вы уловите.
import sys
from tkinter import *
class Editor(Frame):
# это все херня, просто бросаем виджеты на форму
def __init__(self, master, **kwargs):
Frame.__init__(self, master)
if 'width' not in kwargs:
kwargs['width'] = 30
self.left = Text(self, **kwargs) #Левый тексвиджет
self.left['font']='Monoserif 12'
self.left.pack(side=LEFT, fill=BOTH, expand=True)
self.right = Text(self, **kwargs) #Правый тексвиджет
self.right['font']='Monoserif 12'
self.scrollbarLeft = Scrollbar(self)
self.scrollbarLeft.pack(side=LEFT, fill=Y)
self.left.config(yscrollcommand=self.scrollbarLeft.set)
self.scrollbarLeft.config(command=self.left.yview)
self.right.pack(side=LEFT, fill=BOTH, expand=True)
self.scrollbarRight = Scrollbar(self)
self.scrollbarRight.pack(side=RIGHT, fill=Y)
self.right.config(yscrollcommand=self.scrollbarRight.set)
self.scrollbarRight.config(command=self.right.yview)
commands = '<Up>','<Down>','<Left>','<Right>'
for command in commands:
self.right.bind(command,self.cursorMoved)
self.currentString = 0
self.markedString = 0
self.left.tag_config('bold',font='Monoserif 12 bold')
self.right.tag_config('bold',font='Monoserif 12 bold')
def cursorMoved(self,event):
# курсор перемещаеться на следующую строку, подсвечивается следующая строка
_pos = self.right.index(INSERT)
pos = _pos.split('.')
if self.currentString != pos[0]:
self.currentString = pos[0]
if self.currentString != self.markedString:
self.left.tag_remove('bold',str(self.markedString)+'.0',str(self.markedString)+'.end')
self.right.tag_remove('bold',str(self.markedString)+'.0',str(self.markedString)+'.end')
self.markedString = self.currentString
self.left.tag_add('bold',str(self.markedString)+'.0',str(self.markedString)+'.end')
self.right.tag_add('bold',str(self.markedString)+'.0',str(self.markedString)+'.end')
self.left.see(_pos)
# тут начинаеться алгоритм подгонки строк
leftStrPos = self.left.bbox(str(pos[0])+'.0') # координаты начала текущей строки справа
rightStrPos = self.right.bbox(str(pos[0])+'.0') # координаты начала текущей строки слева
if leftStrPos == None: # если символ невидим bbox возвращает None
return True
if rightStrPos == None:
self.left.see(str(self.markedString)+'.0')
return True
leftY = leftStrPos[1] # У координата начала левой строки
rightY = rightStrPos[1] # У координата начала правой строки
if leftY - rightY > 0: # если леваяч строка ниже правой
while leftY >= rightY+8 and self.left.yview()[1]<1: # пока левая строка ниже прапвой или пока не упремся в низ
self.left.yview_scroll(1, 'unit') # сдвигаем левую строку на 1 строку вверх
leftStrPos = self.left.bbox(str(pos[0])+'.0') # обновляем У координату левой строки
leftY = leftStrPos[1]
else: # иначе левая строка выше
while leftY <= rightY-8 and self.left.yview()[0]>0: # пока левая строка выше правой или пока не упремся в верх
self.left.yview_scroll(-1, 'unit') # сдвигаем левую строку 1 строку вниз
leftStrPos = self.left.bbox(str(pos[0])+'.0') # обновляем У координату левой строки
leftY = leftStrPos[1]
if __name__ == '__main__':
root = Tk()
mainWin = Editor(root)
mainWin.pack(fill=BOTH, expand=True)
text1 = '''He broke the seal and glanced over the contents.
"Oh, come, it may prove to be something of interest, after all."
"Not social, then?"
"No, distinctly professional."
"And from a noble client?"
"One of the highest in England."
"My dear fellow. I congratulate you."
'''
text1 = text1.splitlines()
for i in range(len(text1)):
text1[i] = (text1[i] + ' ') * 10
text1 = '\n'.join(text1)
text2 = '''Он сломал печать и быстро просмотрел содержимое.
"Э, нет, здесь всё-таки может оказаться кое-что интересное."
"Значит, это не светское письмо?"
"Нет, сугубо деловое."
"От знатного клиента?"
"Одного из самых знатных в Англии."
"Поздравляю Вас, мой друг."
'''
text2 = text2.splitlines()
for i in range(len(text2)):
text2[i] = (text2[i] + ' ') * 10
text2 = '\n'.join(text2)
text1 = text1 * 5
text2 = text2 * 5
mainWin.left.insert(END,text1)
mainWin.right.insert(END,text2)
root.mainloop()
естественно в начале-конце синхронизация хромает, потому как листать некуда.