我正在使用tkinter创建功能特定的文本编辑器。我想添加书签功能,并看到了几个使用.yview()[0]或.index(INSERT)的示例,以获取yview的第一行号或应添加书签的行的实际行号。我不知道如何根据对文本框其他部分的行插入/删除来调整书签。我正在使用Bryan Oakley共享的一些很棒的代码来为文本框创建行号。该代码还提供了一个“代理”功能,该功能允许创建虚拟事件来处理不同的tkinter函数(例如,插入,删除,替换等)。这是代码(经过微调以处理不同字体大小的间距):
class TextLineNumbers(tk.Canvas):
def __init__(self, *args, **kwargs):
tk.Canvas.__init__(self, *args, **kwargs)
self.textwidget = None
self.font_spacing = 0
self.setfontspacing(self.font_spacing)
def attach(self, text_widget):
self.textwidget = text_widget
def setfontspacing(self, spacing):
self.font_spacing = spacing
def redraw(self, *args):
'''redraw line numbers'''
self.delete("all")
i = self.textwidget.index("@0,0")
while True :
dline= self.textwidget.dlineinfo(i)
if dline is None: break
y = dline[1] + self.font_spacing
linenum = str(i).split(".")[0].zfill(7)
self.create_text(2,y,anchor="nw", text=linenum)
i = self.textwidget.index("%s+1line" % i)
class CustomText(tk.Text):
def __init__(self, *args, **kwargs):
tk.Text.__init__(self, *args, **kwargs)
# create a proxy for the underlying widget
self._orig = self._w + "_orig"
self.tk.call("rename", self._w, self._orig)
self.tk.createcommand(self._w, self._proxy)
def _proxy(self, *args):
# let the actual widget perform the requested action
cmd = (self._orig,) + args
result=None
try:
result = self.tk.call(cmd)
except Exception:
pass
# generate an event if something was added or deleted,
# or the cursor position changed
# print(cmd, args, "=>", result)
if (args[0] in ("insert", "replace", "delete") or
args[0:3] == ("mark", "set", "insert") or
args[0:2] == ("xview", "moveto") or
args[0:2] == ("xview", "scroll") or
args[0:2] == ("yview", "moveto") or
args[0:2] == ("yview", "scroll")
):
self.event_generate("<<Change>>", when="tail")
if (args[0] in ("insert", "replace", "delete") ):
self.event_generate("<<Text_Change>>", when="now")
# return what the actual widget returned
return result
我已将Text_Change事件绑定到我的自定义文本窗口小部件,它使我可以跟踪更改(即查看是否已发生更改并在退出时提示进行保存等)。所以那部分工作正常。
但是,这些事件发生时,我不知道如何捕获有关插入/删除的行的详细信息。 print(cmd,args,“ =>”,result)提供了很多细节,我想我可以找到一种基于该信息计算增量的方法,但这似乎是一个复杂的解决方案。
我想知道是否有人解决过这个问题,并且可能会提出建议。或者也许只是我要忽略的一个简单得多的解决方案。
谢谢
文本小部件可以通过mark_set
命令设置书签。标记可以像文本小部件索引一样使用。例如,您可以在长文件的末尾设置标记“页脚”,然后使用see
方法使页脚可见。
标记代表两个索引之间的间隔。如果在索引“ 200.0”处设置标记,则该标记表示先前索引和该索引之间的空间。标记将“粘在”间隙的一侧或另一侧。默认情况下,它的字符会保留在右侧,但是可以使用mark_gravity
方法更改该方法,该方法可以接受“左”或“右”。
这里是一个人为设计的示例,该示例在第200行设置了一个书签,然后提供了一个跳转到该标记的按钮。请注意,即使在程序启动后,您也可以插入任意行,并且标记仍将“粘”在单词“ This”(或更确切地说,字母“ T”)上。
import tkinter as tk
root = tk.Tk()
text = tk.Text(root, height=20, yscrollcommand=lambda *args: vsb.set(*args))
vsb = tk.Scrollbar(root, orient="vertical", command=text.yview)
jump = tk.Button(root, text="Jump to bookmark", command=lambda: text.see("bookmark"))
jump.pack(side="top")
vsb.pack(side="right", fill="y")
text.pack(side="left", fill="both", expand=True)
for i in range(300):
text.insert("end", f"Lorem ipsum dolar set\n")
text.insert("200.0", "This line is bookmarked\n")
text.mark_set("bookmark", "200.0")
root.mainloop()