Нумерация строк, tkinter

я пытаюсь сделать нумерацию строк в текстовом редакторе. Я нашёл код на нумерацию строк от Брайана Окли и я попробовал его задействовать в своем коде. Вот тут я запутался, теперь я не понимаю как сделать чтобы нумерация строк была в одном текстовом поле. Вот код:

from tkinter import *
from tkinter import filedialog, ttk
import tkinter as tk
from lines import TextLineNumbers, CustomText, Example
import os


title = 'Notepad'
root = Tk()
root.geometry('800x600')
root.title(title)


tabs = {'ky': 0}
tab_list = []

# Example(root).pack(side="top", fill="both", expand=True)
notebook = ttk.Notebook(root)

# --------------------

def open_file():
    textWidget = Text(root)
    file = open(filedialog.askopenfilename(), 'r')
    title = os.path.basename(file.name)
    tab = add_tab(title)
    root.title(title + " - Notepad")
    data = file.read()
    tab.textWidget.delete(1.0, "end")
    tab.textWidget.insert(1.0, data)
    file.close()


def add_tab(name):
    notebook.pack(expand=True, fill='both')
    tab = Tab(notebook, name)
    print(name)
    notebook.add(tab, text=name)
    tab_list.append(tab)
    return tab

def save_file():
    tab_to_save = get_tab()
    print(tab_to_save)
    tab_to_save.save_tab()

def get_tab():
    print(notebook.index('current'))
    #Get the tab object from the tab_list based on the index of the currently selected tab
    tab = tab_list[notebook.index('current')]
    return tab

def generate_tab():
    if tabs['ky'] < 20:
        tabs['ky'] += 1
        add_tab('Document ' + str(tabs['ky']))

def run():
        root.mainloop()

# --------------------

menubar = Menu(root)
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label="New...", command= generate_tab)
filemenu.add_command(label="Open", command = open_file)
filemenu.add_command(label="Save", command= save_file)
filemenu.add_separator()
filemenu.add_command(label="Exit", command= root.quit)
menubar.add_cascade(label="File", menu = filemenu)

editmenu = Menu(menubar, tearoff=0)
editmenu.add_command(label="Undo")
editmenu.add_command(label="Redo")
menubar.add_cascade(label="Edit", menu=editmenu)
root.config(menu=menubar)

class Tab(Frame):

    def __init__(self, root, name):
        Frame.__init__(self, root)

        self.root = root
        self.name = name

        self.textWidget = Text(self, font = "DejaVuSansMono 10", fg = "#111")
        self.textWidget["bg"] = "#fff"
        self.textWidget.pack(fill='both', expand=True)

    def save_tab(self):
        print(self.textWidget.get("1.0", 'end-1c'))
        file = open(filedialog.asksaveasfilename() + '.txt', 'w+')
        file.write(self.textWidget.get("1.0", 'end-1c'))
        print(os.path.basename(file.name))
        #title = os.path.basename(file.name)
        file.close()

# --------------------



if __name__ == '__main__':
    print("done!")
    run()

введите сюда описание изображения


Ответы (1 шт):

Автор решения: insolor

Нужно создавать CustomText внутри вашего таба вместо Text, там же привязывать панель с номерами строк, и добавить скроллбар, все по аналогии с кодом из класса Example:

class Tab(Frame):

    def __init__(self, root, name):
        Frame.__init__(self, root)

        self.root = root
        self.name = name

        # Текстовое поле
        self.textWidget = CustomText(self, font = "DejaVuSansMono 10", fg = "#111", bg = "#fff")
        
        # Панель с номерами строк
        linenumbers = TextLineNumbers(self, width=30)
        linenumbers.attach(self.textWidget)
        
        # Перерисовка панели с номерами при изменениях в текстовом виджете
        def on_change(event):
            linenumbers.redraw()
        
        self.textWidget.bind("<<Change>>", on_change)
        self.textWidget.bind("<Configure>", on_change)
        
        # Вертикальная полоса прокрутки
        vsb = tk.Scrollbar(self, orient="vertical", command=self.textWidget.yview)
        self.textWidget.configure(yscrollcommand=vsb.set)
        
        # Размещаем панель номеров слева, полосу прокрутки справа,
        # потом уже текстовое поле на оставшемся месте между ними
        linenumbers.pack(side="left", fill="y")
        vsb.pack(side="right", fill="y")
        self.textWidget.pack(fill='both', expand=True)

Сравните с классом Example из ответа:

class Example(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
        self.text = CustomText(self)
        self.vsb = tk.Scrollbar(orient="vertical", command=self.text.yview)
        self.text.configure(yscrollcommand=self.vsb.set)
        self.text.tag_configure("bigfont", font=("Helvetica", "24", "bold"))
        self.linenumbers = TextLineNumbers(self, width=30)
        self.linenumbers.attach(self.text)

        self.vsb.pack(side="right", fill="y")
        self.linenumbers.pack(side="left", fill="y")
        self.text.pack(side="right", fill="both", expand=True)

        self.text.bind("<<Change>>", self._on_change)
        self.text.bind("<Configure>", self._on_change)

        ...

    def _on_change(self, event):
        self.linenumbers.redraw()

Все примерно то же самое, только я не стал делать панель номеров и сколлбар полями объекта Tab, и немного по-другому организовал код.

Скриншот

→ Ссылка