Python 如何获取当前行的行索引
我从YouTube教程中获得了一个测试编辑器。 我试图突出显示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
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()