【发布时间】:2015-07-17 22:26:23
【问题描述】:
我正在使用 Bryan Oakley 在 Tkinter adding line number to text widget 的代码创建带有行号的 Text 小部件。但我想创建一个自定义小部件,我可以像Text 小部件一样使用它,但随后带有可选的行号。喜欢在:
t = LinedText(top)
t.insert("insert", "Hello")
t.show()
但到目前为止,当我显示行号时,它会覆盖文本小部件。窗口会自动调整大小。为什么会这样?我的代码:
import tkinter as tk
class TextLineNumbers(tk.Canvas):
def __init__(self, *args, **kwargs):
tk.Canvas.__init__(self, *args, **kwargs)
self.textwidget = None
def attach(self, text_widget):
self.textwidget = text_widget
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]
linenum = str(i).split(".")[0]
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)
self.tk.eval('''
proc widget_proxy {widget widget_command args} {
# call the real tk widget command with the real args
set result [uplevel [linsert $args 0 $widget_command]]
# generate the event for certain types of commands
if {([lindex $args 0] in {insert replace delete}) ||
([lrange $args 0 2] == {mark set insert}) ||
([lrange $args 0 1] == {xview moveto}) ||
([lrange $args 0 1] == {xview scroll}) ||
([lrange $args 0 1] == {yview moveto}) ||
([lrange $args 0 1] == {yview scroll})} {
event generate $widget <<Change>> -when tail
}
# return the result from the real widget command
return $result
}
''')
self.tk.eval('''
rename {widget} _{widget}
interp alias {{}} ::{widget} {{}} widget_proxy {widget} _{widget}
'''.format(widget=str(self)))
class LinedText(CustomText):
def __init__(self, *args, **kwargs):
CustomText.__init__(self, *args, **kwargs)
self.settings = self.Settings()
self.linenumbers = None
self.text = super()
self.vsb = tk.Scrollbar(orient="vertical", command=self.yview)
self.vsb.pack(side="right", fill="y")
self.text.configure(yscrollcommand=self.vsb.set)
self.text.tag_configure("bigfont", font=("Helvetica", "24", "bold"))
self.text.pack(side="left", fill="both", expand=True)
self.text.bind("<<Change>>", self._on_change)
self.text.bind("<Configure>", self._on_change)
self.text.insert("end", "one\ntwo\nthree\n")
self.text.insert("end", "four\n",("bigfont",))
self.text.insert("end", "five\n")
self.text.pack(side="left")
def hide(self,event=None):
if not self.settings.hide_linenumbers:
self.settings.hide_linenumbers = True
self.linenumbers.pack_forget()
def show(self,event=None):
if self.linenumbers == None:
self.linenumbers = TextLineNumbers(self, width=30)
self.linenumbers.attach(self.text)
self.linenumbers.pack(side="left", fill="y")
elif self.settings.hide_linenumbers:
self.settings.hide_linenumbers = False
self.linenumbers.pack(side="left", fill="y")
def _on_change(self, event):
if self.linenumbers:
self.linenumbers.redraw()
class Settings():
def __init__(self):
self.hide_linenumbers = True
if __name__ == "__main__":
root = tk.Tk()
text = LinedText(root)
#text.pack(side="right", fill="both", expand=True)
button = tk.Button(root, text="Hide", command=text.hide)
button.pack()
button = tk.Button(root, text="Show", command=text.show)
button.pack()
root.mainloop()
另外,我假设使用.pack() 而不是.pack(side="left"),小部件将绘制在以前的小部件下方。我的按钮被向右绘制。如何让他们在文本和线条小部件下方绘制?我是否绝对需要使用.grid() 或Frame?
【问题讨论】:
标签: python tkinter tkinter-canvas