Python 如何获取当前行的行索引

Python 如何获取当前行的行索引,python,python-3.x,tkinter,tkinter-text,Python,Python 3.x,Tkinter,Tkinter Text,我从YouTube教程中获得了一个测试编辑器。 我试图突出显示python的语句,但当我编写语句时,它会将所有行着色,我认为问题在于使用我创建的索引 代码如下: import tkinter as tk from tkinter import filedialog from tkinter import messagebox class Menubar: def __init__(self, parent): font_specs = 14

我从YouTube教程中获得了一个测试编辑器。 我试图突出显示python的语句,但当我编写语句时,它会将所有行着色,我认为问题在于使用我创建的索引

代码如下:

import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox


class Menubar:

    def __init__(self, parent):
        font_specs = 14
        
        menubar = tk.Menu(parent.master)
        parent.master.config(menu = menubar)

        file_dropdown = tk.Menu(menubar, font = font_specs, tearoff = 0)
        file_dropdown.add_command(label = "Nuovo file",
                                  accelerator = "Ctrl + N",
                                  command = parent.new_file)

        file_dropdown.add_command(label = "Apri file",
                                  accelerator = "Ctrl + O",
                                  command = parent.open_file)

        file_dropdown.add_command(label = "Salva",
                                  accelerator = "Ctrl + S",
                                  command = parent.save)

        file_dropdown.add_command(label = "Salva con nome",
                                  accelerator = "Ctrl + Shit + S",
                                  command = parent.save_as)

        file_dropdown.add_separator()

        file_dropdown.add_command(label = "Esci",
                                  command = parent.master.destroy)

        about_dropdown = tk.Menu(menubar, font = font_specs, tearoff = 0)
        about_dropdown.add_command(label = "Note di rilascio",
                                   command = self.show_about_message)

        about_dropdown.add_separator()

        about_dropdown.add_command(label = "About",
                                   command = self.show_release_notes)

        settings_dropdown = tk.Menu(menubar, font = font_specs, tearoff = 0)
        settings_dropdown.add_command(label = "Cambia lo sfondo dell'editor",
                                      command = parent.change_background)

        menubar.add_cascade(label = "File", menu = file_dropdown)
        menubar.add_cascade(label = "About", menu = about_dropdown)
        menubar.add_cascade(label = "Settings", menu = settings_dropdown)


    def show_about_message(self):
        box_title = "Riguardo PyText"
        box_message = "Il mio primo editor testuale creato con Python e TkInter!"

        messagebox.showinfo(box_title, box_message)


    def show_release_notes(self):
        box_title = "Note di Rilascio"
        box_message = "Versione 0.1 (Beta) Santa"

        messagebox.showinfo(box_title, box_message)
        

class Statusbar:

    def __init__(self, parent):
        font_specs = 12

        self.status = tk.StringVar()
        self.status.set("PyText - 0.1 Santa")

        label = tk.Label(parent.text_area, textvariable = self.status,
                         fg = "black", bg = "lightgrey", anchor = "sw")

        label.pack(side = tk.BOTTOM, fill = tk.BOTH)

    def update_status(self, *args):
        if isinstance(args[0], bool):
            self.status.set("Il tuo file è stato salvato!")

        else:
            self.status.set("PyText - 0.1 Santa")


class PyText:
    """
    Classe-Madre dell'applicazione
    """

    def __init__(self, master):
        master.title("Untitled - PyText")
        master.geometry("1200x700")

        font_specs = 18
        
        self.master = master
        self.filename = None
        
        self.text_area = tk.Text(master, font = font_specs, insertbackground = "black")
        self.scroll = tk.Scrollbar(master, command = self.text_area.yview)
        self.text_area.configure(yscrollcommand = self.scroll.set)
        self.text_area.pack(side = tk.LEFT, fill = tk.BOTH, expand = True)
        self.scroll.pack(side = tk.RIGHT, fill = tk.Y)

        self.menubar = Menubar(self)
        self.statusbar = Statusbar(self)
        self.bind_shortcuts()

        
    def set_window_title(self, name = None):
        if name:
            self.master.title(name + " - PyText")
            
        else:
            self.master.title("Untitled - PyText")    


    def new_file(self, *args):
        self.text_area.delete(1.0, tk.END)
        self.filename = None

        self.set_window_title()


    def open_file(self, *args):
        self.filename = filedialog.askopenfilename(
            defaultextension = ".txt",
            filetypes = [("Tutti i file", "*.*"),
                         ("File di Testo", "*.txt"),
                         ("Script Python", "*.py"),
                         ("Markdown Text", "*.md"),
                         ("File JavaScript", "*.js"),
                         ("Documenti Html", "*.html"),
                         ("Documenti CSS", "*.css"),
                         ("Programmi Java", "*.java")]
        )

        if self.filename:
            self.text_area.delete(1.0, tk.END)

            with open(self.filename, "r") as f:
                self.text_area.insert(1.0, f.read())

            self.set_window_title(self.filename)


    def save(self, *args):
        if self.filename:
            try:
                textarea_content = self.text_area.get(1.0, tk.END)
                with open(self.filename, "w") as f:
                    f.write(textarea_content)

                self.statusbar.update_status(True)

            except Exception as e:
                print(e)

        else:
            self.save_as()


    def save_as(self, *args):
        try:
            new_file = filedialog.asksaveasfilename(
                initialfile = "Untitled.txt",
                defaultextension = ".txt",
                filetypes = [("Tutti i file", "*.*"),
                             ("File di Testo", "*.txt"),
                             ("Script Python", "*.py"),
                             ("Markdown Text", "*.md"),
                             ("File JavaScript", "*.js"),
                             ("Documenti Html", "*.html"),
                             ("Documenti CSS", "*.css"),
                             ("Programmi Java", "*.java")]
                )

            textarea_content = self.text_area.get(1.0, tk.END)
            with open(new_file, "w") as f:
                f.write(textarea_content)

            self.filename = new_file
            self.set_window_title(self.filename)
            self.statusbar.update_status(True)

        except Exception as e:
            print(e)


    def change_background(self):
        self.text_area.config(background = "black", foreground = "white", 
                              insertbackground = "white", insertwidth = 2)

        
    def highlight_text(self, *args):
        tags = {
            "import": "pink",
            "from": "pink",
            "def": "blue",
            "for": "purple",
            "while": "purple"
        }

        textarea_content = self.text_area.get(1.0, tk.END)
        lines = textarea_content.split("\n")

        for row in lines:
            for tag in tags:
                index = row.find(tag) + 1.0

                if index > 0.0:
                    self.text_area.tag_add(tag, index, index + len(tag) -1)
                    self.text_area.tag_config(tag, foreground = tags.get(tag))

                    print("Nuovo tag aggiunto:", tag)
            
        print("Funzione eseguita:", args, "\n")
    
    
    def bind_shortcuts(self):
        self.text_area.bind("<Control-n>", self.new_file)
        self.text_area.bind("<Control-o>", self.open_file)
        self.text_area.bind("<Control-s>", self.save)
        self.text_area.bind("<Control-S>", self.save_as)
        self.text_area.bind("<Key>", self.highlight_text, self.statusbar.update_status)

    
if __name__ == "__main__":
    master = tk.Tk()
    pt = PyText(master)
    master.mainloop()
将tkinter作为tk导入
从tkinter导入文件对话框
从tkinter导入消息框
类菜单栏:
定义初始化(自身,父级):
字体规格=14
menubar=tk.Menu(parent.master)
parent.master.config(menu=menubar)
文件下拉菜单=tk.Menu(菜单栏,字体=font\u规格,tearoff=0)
文件下拉菜单。添加命令(label=“Nuovo file”,
加速器=“Ctrl+N”,
command=parent.new_文件)
文件\下拉菜单。添加\命令(label=“Apri file”,
加速器=“Ctrl+O”,
command=parent.open_文件)
文件下拉菜单。添加命令(label=“Salva”,
加速器=“Ctrl+S”,
command=parent.save)
文件下拉菜单。添加命令(label=“Salva con nome”,
加速器=“Ctrl+Shit+S”,
命令=父项。另存为)
文件\下拉列表。添加\分隔符()
文件下拉菜单。添加命令(label=“Esci”,
command=parent.master.destroy)
关于下拉菜单=tk.菜单(菜单栏,字体=font\u规格,tearoff=0)
关于下拉菜单。添加命令(label=“Note di rilascio”,
command=self.show_about_消息)
关于_下拉列表。添加_分隔符()
关于\u下拉菜单。添加\u命令(label=“about”,
command=self.show\u release\u notes)
设置下拉菜单(菜单栏,字体规格,tearoff=0)
设置下拉菜单。添加命令(label=“Cambia lo sfondo dell'editor”,
命令=父项。更改(背景)
menubar.add\u级联(label=“File”,menu=File\u下拉列表)
菜单栏.add_级联(label=“About”,menu=About_下拉列表)
菜单栏。添加级联(label=“Settings”,menu=Settings\u下拉列表)
def显示关于消息(自我):
box_title=“Riguardo PyText”
box_message=“Il mio primo editor testuale creator con Python e TkInter!”
messagebox.showinfo(框标题,框消息)
def显示发布说明(自我):
box_title=“注意事项”
box_message=“版本0.1(测试版)圣诞老人”
messagebox.showinfo(框标题,框消息)
类状态栏:
定义初始化(自身,父级):
字体规格=12
self.status=tk.StringVar()
self.status.set(“PyText-0.1”)
label=tk.label(parent.text_区域,textvariable=self.status,
fg=“黑色”,bg=“浅灰色”,anchor=“西南”)
标签包装(侧面=底部,填充=底部)
def更新_状态(自身,*args):
如果isinstance(参数[0],布尔值):
self.status.set(“Il tuo fileèstato salvato!”)
其他:
self.status.set(“PyText-0.1”)
类PyText:
"""
马德雷·戴尔应用酒店
"""
定义初始(自我,主):
主标题(“无标题-PyText”)
几何硕士(“1200x700”)
字体规格=18
self.master=master
self.filename=None
self.text\u area=tk.text(master,font=font\u specs,insertbackground=“black”)
self.scroll=tk.Scrollbar(主控,命令=self.text\u area.yview)
self.text\u area.configure(yscrollcommand=self.scroll.set)
self.text\u area.pack(side=tk.LEFT,fill=tk.BOTH,expand=True)
self.scroll.pack(side=tk.RIGHT,fill=tk.Y)
self.menubar=菜单栏(self)
self.statusbar=状态栏(self)
self.bind_快捷方式()
def设置窗口标题(自身,名称=无):
如果名称:
self.master.title(name+“-PyText”)
其他:
self.master.title(“无标题-PyText”)
def新_文件(自身,*args):
self.text_area.delete(1.0,tk.END)
self.filename=None
self.set_window_title()
def open_文件(自身,*args):
self.filename=filedialog.askopenfilename(
defaultextension=“.txt”,
filetypes=[(“Tutti文件”、“**”),
(“文件di Testo”,“*.txt”),
(“脚本Python”,“*.py”),
(“减价文本”、“*.md”),
(“文件JavaScript”,“*.js”),
(“Documenti Html”,“*.Html”),
(“Documenti CSS”,“*.CSS”),
(“Programmi Java”,“*.Java”)]
)
如果self.filename:
self.text_area.delete(1.0,tk.END)
将open(self.filename,“r”)作为f:
self.text_area.insert(1.0,f.read())
self.set\u窗口\u标题(self.filename)
def保存(自身,*参数):
如果self.filename:
尝试:
textarea\u content=self.text\u area.get(1.0,tk.END)
将open(self.filename,“w”)作为f:
f、 写入(文本区域内容)
self.statusbar.update\u状态(True)
例外情况除外,如e:
打印(e)
其他:
self.save_as()
def另存为(自身,*参数):
尝试:
新建文件=filedialog.asksaveasfilename(
initialfile=“Untitled.txt”,
defaultextension=“.txt”,
filetypes=[(“Tutti文件”、“**”),
(“文件di Testo”,“*.txt”),
(“脚本Python”,“*.py”),
(“减价文本”、“*.md”),
(“文件JavaScript”,“*.js”),
for y, row in enumerate(lines, 1):
start = '{}.{}'.format(y, x)
end   = '{}.{}'.format(y, x+len(tag))
for y, row in enumerate(lines, 1):
    for tag in tags:

        x = row.find(tag)

        if x > -1:
            print(f"{tag} | x: {x} | y: {y}")

            start = '{}.{}'.format(y, x)
            end   = '{}.{}'.format(y, x+len(tag))

            print(f"{tag} | start: {start} | end: {end}")

            self.text_area.tag_add(tag, start, end)
            self.text_area.tag_config(tag, foreground = tags.get(tag))
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
import os

print(os.getcwd())

class Menubar:

    def __init__(self, parent):
        font_specs = 14
        
        menubar = tk.Menu(parent.master)
        parent.master.config(menu = menubar)

        file_dropdown = tk.Menu(menubar, font = font_specs, tearoff = 0)
        file_dropdown.add_command(label = "Nuovo file",
                                  accelerator = "Ctrl + N",
                                  command = parent.new_file)

        file_dropdown.add_command(label = "Apri file",
                                  accelerator = "Ctrl + O",
                                  command = parent.open_file)

        file_dropdown.add_command(label = "Salva",
                                  accelerator = "Ctrl + S",
                                  command = parent.save)

        file_dropdown.add_command(label = "Salva con nome",
                                  accelerator = "Ctrl + Shift + S",
                                  command = parent.save_as)

        file_dropdown.add_separator()

        file_dropdown.add_command(label = "Esci",
                                  accelerator = "Ctrl + Q",
                                  command = parent.master.destroy)

        about_dropdown = tk.Menu(menubar, font = font_specs, tearoff = 0)
        about_dropdown.add_command(label = "Note di rilascio",
                                   command = self.show_about_message)

        about_dropdown.add_separator()

        about_dropdown.add_command(label = "About",
                                   command = self.show_release_notes)

        settings_dropdown = tk.Menu(menubar, font = font_specs, tearoff = 0)
        settings_dropdown.add_command(label = "Cambia lo sfondo dell'editor",
                                      command = parent.change_background)

        menubar.add_cascade(label = "File", menu = file_dropdown)
        menubar.add_cascade(label = "About", menu = about_dropdown)
        menubar.add_cascade(label = "Settings", menu = settings_dropdown)


    def show_about_message(self):
        box_title = "Riguardo PyText"
        box_message = "Il mio primo editor testuale creato con Python e TkInter!"

        messagebox.showinfo(box_title, box_message)


    def show_release_notes(self):
        box_title = "Note di Rilascio"
        box_message = "Versione 0.1 (Beta) Santa"

        messagebox.showinfo(box_title, box_message)
        

class Statusbar:

    def __init__(self, parent):
        font_specs = 12

        self.status = tk.StringVar()
        self.status.set("PyText - 0.1 Santa")

        label = tk.Label(parent.text_area, textvariable = self.status,
                         fg = "black", bg = "lightgrey", anchor = "sw")

        label.pack(side = tk.BOTTOM, fill = tk.BOTH)

    def update_status(self, *args):
        if isinstance(args[0], bool):
            self.status.set("Il tuo file è stato salvato!")

        else:
            self.status.set("PyText - 0.1 Santa")


class PyText:
    """
    Classe-Madre dell'applicazione
    """

    def __init__(self, master):
        master.title("Untitled - PyText")
        master.geometry("1200x700")

        font_specs = 18
        
        self.master = master
        self.filename = None
        
        self.text_area = tk.Text(master, font = font_specs, insertbackground = "black")
        self.scroll = tk.Scrollbar(master, command = self.text_area.yview)
        self.text_area.configure(yscrollcommand = self.scroll.set)
        self.text_area.pack(side = tk.LEFT, fill = tk.BOTH, expand = True)
        self.scroll.pack(side = tk.RIGHT, fill = tk.Y)

        self.menubar = Menubar(self)
        self.statusbar = Statusbar(self)
        self.bind_shortcuts()

        
    def set_window_title(self, name = None):
        if name:
            self.master.title(name + " - PyText")
            
        else:
            self.master.title("Untitled - PyText")    


    def new_file(self, *args):
        self.text_area.delete(1.0, tk.END)
        self.filename = None

        self.set_window_title()


    def open_file(self, *args):
        self.filename = filedialog.askopenfilename(
            initialdir = os.getcwd(),
            defaultextension = ".txt",
            filetypes = [("Tutti i file", "*.*"),
                         ("File di Testo", "*.txt"),
                         ("Script Python", "*.py"),
                         ("Markdown Text", "*.md"),
                         ("File JavaScript", "*.js"),
                         ("Documenti Html", "*.html"),
                         ("Documenti CSS", "*.css"),
                         ("Programmi Java", "*.java")]
        )

        if self.filename:
            self.text_area.delete(1.0, tk.END)

            with open(self.filename, "r") as f:
                self.text_area.insert(1.0, f.read())

            self.set_window_title(self.filename)


    def save(self, *args):
        if self.filename:
            try:
                textarea_content = self.text_area.get(1.0, tk.END)
                with open(self.filename, "w") as f:
                    f.write(textarea_content)

                self.statusbar.update_status(True)

            except Exception as e:
                print(e)

        else:
            self.save_as()


    def save_as(self, *args):
        try:
            new_file = filedialog.asksaveasfilename(
                initialfile = "Untitled.txt",
                defaultextension = ".txt",
                filetypes = [("Tutti i file", "*.*"),
                             ("File di Testo", "*.txt"),
                             ("Script Python", "*.py"),
                             ("Markdown Text", "*.md"),
                             ("File JavaScript", "*.js"),
                             ("Documenti Html", "*.html"),
                             ("Documenti CSS", "*.css"),
                             ("Programmi Java", "*.java")]
                )

            textarea_content = self.text_area.get(1.0, tk.END)
            with open(new_file, "w") as f:
                f.write(textarea_content)

            self.filename = new_file
            self.set_window_title(self.filename)
            self.statusbar.update_status(True)

        except Exception as e:
            print(e)


    def change_background(self):
        self.text_area.config(background = "black", foreground = "white", 
                              insertbackground = "white", insertwidth = 2)

        
    def highlight_text_old(self, *args):
        tags = {
            "import": "pink",
            "from": "red",
            "def": "blue",
            "for": "purple",
            "while": "green",
        }

        textarea_content = self.text_area.get(1.0, tk.END)
        lines = textarea_content.split("\n")

        for y, row in enumerate(lines, 1):
            for tag in tags:
                x = row.find(tag)
                if x > -1:
                    print(f"{tag} | x: {x} | y: {y}")
                    start = '{}.{}'.format(y, x)
                    end   = '{}.{}'.format(y, x+len(tag))
                    print(f"{tag} | start: {start} | end: {end}")
                    self.text_area.tag_add(tag, start, end)
                    self.text_area.tag_config(tag, foreground = tags.get(tag))

                    #print("Nuovo tag aggiunto:", tag)
            
        #print("Funzione eseguita:", args, "\n")

    def highlight_text(self, *args):
        # TODO: move to `__init__` ?
        tags = {
            "import": "pink",
            "from": "red",
            "def": "blue",
            "for": "purple",
            "while": "green",
        }

        # TODO: move to `__init__` ?
        # create tags with assigned color - do it only onve (in __init__)
        for color in ['pink', 'red', 'blue', 'purple', 'green']:
            self.text_area.tag_config(color, foreground=color)

        # remove all tags from text
        for tag in self.text_area.tag_names():
            self.text_area.tag_remove(tag, '1.0', 'end')  # not `tag_remove()`
         

        textarea_content = self.text_area.get(1.0, tk.END)
        lines = textarea_content.split("\n")

        for y, row in enumerate(lines, 1):
            for tag in tags:
                x = row.find(tag)
                if x > -1:
                    print(f"{tag} | x: {x} | y: {y}")
                    match_start = '{}.{}'.format(y, x)
                    match_end   = '{}.{}'.format(y, x+len(tag))
                    print(f"{tag} | start: {match_start} | end: {match_end}")
                    self.text_area.tag_add(tag, match_start, match_end)
                    #self.text_area.tag_config(tag, foreground=tags.get(tag))  # create tags only once - at start

                    #print("Nuovo tag aggiunto:", tag)
            
        #print("Funzione eseguita:", args, "\n")


    def highlight_text_regex(self, *args):
        # TODO: move to `__init__` ?
        tags = {
            "import": "red",
            "from": "red",
            "as": "red",

            "def": "blue",
            "class": "blue",

            "for": "green",
            "while": "green",

            "if": "brown",
            "elif": "brown",
            "else": "brown",

            "print": "purple",            

            "True": "blue",
            "False": "blue",
            "self": "blue",

            "\d+": "red",  # digits

            "__[a-zA-Z][a-zA-Z0-9_]*__": "red",  # ie. `__init__`
        }

        # add `\m \M` to words
        tags = {f'\m{word}\M': tag for word, tag in tags.items()}

        # tags which doesn't work with  `\m \M`
        other_tags = {
            "\(": "brown",  # need `\` because `(` has special meaning
            "\)": "brown",  # need `\` because `)` has special meaning

            ">=": "green",
            "<=": "green",
            "=": "green",
            ">": "green",
            "<": "green",

            "#.*$": "brown",  # comment - to the end of line `$`
        }

        # create one dictionary with all tags
        tags.update(other_tags)

        # TODO: move to `__init__` ?
        # create tags with assigned color - do it only onve (in __init__)
        for color in ['pink', 'red', 'blue', 'purple', 'green', 'brown', 'yellow']:
            self.text_area.tag_config(color, foreground=color)

        # remove all tags from text before adding all tags again (to change color when ie. `def` change to `define`)
        for tag in self.text_area.tag_names():
            self.text_area.tag_remove(tag, '1.0', 'end')  # not `tag_remove()`

        count_chars = tk.IntVar() # needs to count matched chars - ie. for digits `\d+`
        # search `word` and add `tag`
        for word, tag in tags.items():
            #pattern = f'\m{word}\M'  # http://tcl.tk/man/tcl8.5/TclCmd/re_syntax.htm#M72
            pattern = word  # http://tcl.tk/man/tcl8.5/TclCmd/re_syntax.htm#M72
            search_start = '1.0'
            search_end   = 'end'
            while True:
                position = self.text_area.search(pattern, search_start, search_end, count=count_chars, regexp=True)
                print('search:', word, position)
                if position:
                    print(f"{word} | pos: {position}")
                    match_start = position
                    match_end   = '{}+{}c'.format(position, count_chars.get()) #len(word)) # use special string `Y.X+Nc` instead values (Y, X+N)
                    print(f"{word} | start: {match_start} | end: {match_end}")
                    self.text_area.tag_add(tag, match_start, match_end)
                    #self.text_area.tag_config(tag, foreground=tags.get(tag))  # create tags only once - at start
                    search_start = match_end  # to search next word
                else:
                    break    

    def quit(self, *args):
        self.master.destroy()

    def bind_shortcuts(self):
        self.master.bind("<Control-n>", self.new_file)
        self.master.bind("<Control-o>", self.open_file)
        self.master.bind("<Control-s>", self.save)
        self.master.bind("<Control-S>", self.save_as)
        self.master.bind("<Control-q>", self.quit)
        self.master.bind("<Key>", self.highlight_text_regex, self.statusbar.update_status)

    
if __name__ == "__main__":
    master = tk.Tk()
    pt = PyText(master)
    master.mainloop()