Нумерация строк в Tkinter

ЗИЛ

Новичок
Пользователь
Янв 3, 2022
43
1
8
При написании текстового редактора хотелось бы иметь нумерацию строк в отдельном виджете. И общий скролл двух виджетов -- виджета с текстом и виджет где отображаются номера строк.
Код сырой, так что не сильно пинайте.
Код:
Код:
import tkinter as tk

root = tk.Tk()
root.title("Текстовый редактор")

scrollbar = tk.Scrollbar()
scrollbar.pack(side='right', fill='y')

text_widget = tk.Text(root)
text_widget.pack(side="right", expand=True, fill="both")
text_widget.focus_set()

line_numbers = tk.Text(root, bg="#f0f0f0", fg='black', width=4, bd=0, highlightthickness=0)
line_numbers.pack(side="left", fill="y")

def on_update(event):
    line_numbers.delete(1.0, "end")
    lines = text_widget.get(1.0, "end").split("\n")
    for i, lines in enumerate(lines, 1):
        line_numbers.insert("end", str(i)+'\n')
    # line_feed()
    #text_widget.insert(tk.END, 2*"\n")
    #print("lines= ", lines)

def on_delete(event):
    ndex=text_widget.index('insert')
    dex=ndex.split('.')[-1]
    if int(dex) == 0 and float(ndex) != 1.0:
        end_str=line_numbers.get("end-1l", "end")
        if end_str == '\n':
            line_numbers.delete("end-1c", "end")
            line_numbers.delete("end-1l", "end")
        else: line_numbers.delete("end-1l", "end")
    else: return

def on_return(event):
#     ln_txt=line_numbers.index("end-1c")
#     print(ln_txt)
#     line_numbers.insert("end", ln_txt.split('.')[0]+'\n')
    end_line=line_numbers.get("end-1l", "end")
    if end_line == '\n':
        line=line_numbers.get(1.0, "end").split('\n')
        print(line)
        count=enumerate(line, 1)

        num_str=int(line[-3])+1
        print(num_str)
        line_numbers.insert("end", str(num_str)+'\n')
    else:
        line_numbers.insert("end", '\n')
        line=line_numbers.get(1.0, "end").split('\n')
        count=enumerate(line, 1)
        num_str=int(line[-3])+1
        line_numbers.insert("end", str(num_str)+'\n')

# def line_feed():
    # line_numbers.insert("end", "5\n")
    # strok=['end-1l', 'end-2l', 'end-3l', 'end-4l', 'end-5l', 'end-6l', 'end-7l', 'end-8l', 'end-9l']
    # #i=0
    # #n=strok[i]
    # for i in range(0, 8):
        # n=strok[i]
        # ln=line_numbers.get(str(n), "end")
        # if ln== '\n':
            # print("n= ", n)
        # else: return
        # i=i+1
        # print("i= ", i)

def on_scrollbar(*args):
    '''прокручивает оба текста при скроллинге'''
    line_numbers.yview(*args)
    text_widget.yview(*args)

def on_textscroll(*args):
    '''передача аргумента скроллинга'''
    scrollbar.set(*args)
    on_scrollbar('moveto', args[0])

text_widget.bind("<<Modified>>", on_update)
text_widget.bind("<Return>", on_return)
text_widget.bind("<BackSpace>", on_delete)
# text_widget.bind("<Button-4>", on_scrollbar)

# text_widget.bind("<Button-5>", on_scrollbar)

scrollbar['command'] = on_scrollbar
line_numbers['yscrollcommand'] = on_textscroll
text_widget['yscrollcommand'] = on_textscroll

root.mainloop()
Из проблем -- разный размер текста в виджетах приводит к тому что линии текста не совпадают.
Прикрутить бы сюда функцию которая выравнивает тексты в виджетах -- всё было бы гораздо лучше.
Есть какие-нибудь идеи?
Да, чуть не забыл -- разность вы не увидите -- там символы перевода строки и другие спецсимволы.
И -- таки и да: код писался под Линём.
 

Vershitel_sudeb

Vershitel sudeb
Команда форума
Модератор
Мар 17, 2021
971
219
43
20
Москва
Примерно так, хотя из-за погрешностей ткинтера, при большом количестве строк, все равно начинает сползать. Возможно виджеты текстовые не на одной высоте

Python:
import tkinter as tk
root = tk.Tk()
root.title("Текстовый редактор")

# Одинаковый размер шрифта
FONT = "Arial 14"
# Одинаковое расстояние между строк
LINE_SPACE = 1

scrollbar = tk.Scrollbar()
scrollbar.pack(side="right", fill="y")
text_widget = tk.Text(root, spacing1=LINE_SPACE, font=FONT)
text_widget.pack(side="right", expand=True, fill="both")
text_widget.focus_set()
line_numbers = tk.Text(
    root,
    bg="#f0f0f0",
    fg="black",
    width=4,
    bd=0,
    highlightthickness=0,
    spacing1=LINE_SPACE,
    font=FONT,
)
line_numbers.pack(side="left", fill="y")

def on_update(event):
    line_numbers.delete(1.0, "end")
    lines = text_widget.get(1.0, "end-1c").split("\n")
    for i, lines in enumerate(lines, 1):
        line_numbers.insert("end", str(i) + "\n")

def on_scrollbar(*args):
    """прокручивает оба текста при скроллинге"""
    line_numbers.yview(*args)
    text_widget.yview(*args)

def on_textscroll(*args):
    """передача аргумента скроллинга"""
    scrollbar.set(*args)
    on_scrollbar("moveto", args[0])

text_widget.bind("<KeyRelease>", on_update)
scrollbar["command"] = on_scrollbar
line_numbers["yscrollcommand"] = on_textscroll
text_widget["yscrollcommand"] = on_textscroll
root.mainloop()
 

ЗИЛ

Новичок
Пользователь
Янв 3, 2022
43
1
8
Видишь ли -- я как раз и не хотел чтобы с каждым нажатием клавиши всё перерисовывалось. Именно для этого я и вводил ф-ции on_delete и on_return.
Я с этого кода, который у вас -- начинал.
А вот поработать с интервалами -- да.
А шрифт по умолчанию одинаковый. Он же задан OS.
При распечатке line -- там вылезают символы перевода и ещё что-то. Вот из-за них и неодинаковое количество строк.
 

Форум IT Специалистов