python - Why is my widget being overlapped? -
i using bryan oakley's code @ tkinter adding line number text widget create text
widget line numbers. want create custom widget can use text
widget optional line numbers. in:
t = linedtext(top) t.insert("insert", "hello") t.show()
but of now, when show line numbers, covers text widget. window resized automatically. why happening? code:
import tkinter 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") = self.textwidget.index("@0,0") while true : dline= self.textwidget.dlineinfo(i) if dline none: break y = dline[1] linenum = str(i).split(".")[0] self.create_text(2,y,anchor="nw", text=linenum) = 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 real tk widget command real args set result [uplevel [linsert $args 0 $widget_command]] # generate event 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 result 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()
also, assuming .pack()
opposed .pack(side="left")
, widget drawn below previous widgets. buttons being drawn right. how them draw below text , line widgets? absolutely need use .grid()
or frame
?
first of all, not sure understood logic in functions show
, hide
, in code below, see, have changed little bit functions.
i not sure why using super()
initialise self.text
in linedtext
class, think problem starts there.
what first did make linedtext
inherit frame
instead of customtext
, , create instance variable called self.text
of type customtext
in linedtext
class. did because think of linedtext
class container 2 other objects of type customtext
, textlinenumbers
.
i decided split main window (the root
) in 2 frames, 1 linedtext
object, , 1 contain buttons show
, hide
. in way, can pack frames, instead of single widgets, , can example pack frame buttons @ bottom, , frame linedtext
object @ top.
using frames
organise data right , easier way go when creating layouts.
one thing changed make textlinenumber
pretty numbers drawn. check comments on code.
another thing want should compare value of object none
using is
or is not
, instead of ==
, !=
.
also, not seeing point of having class (settings
) instance variable, not make sense, , guess doing because class become larger in future.
if have problems regarding fact window shrinks when introduce or remove widget, check out question
i hope understand logic of methods show
, hide
, if not, ask.
here's full code:
import tkinter 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") = self.textwidget.index("@0,0") while true : dline= self.textwidget.dlineinfo(i) if dline none: break y = dline[1] linenum = str(i).split(".")[0] # changed text draw: starts 4 self.create_text(4, y, anchor="nw", text=linenum) = 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 real tk widget command real args set result [uplevel [linsert $args 0 $widget_command]] # generate event 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 result real widget command return $result } ''') self.tk.eval(''' rename {widget} _{widget} interp alias {{}} ::{widget} {{}} widget_proxy {widget} _{widget} '''.format(widget=str(self))) class linedtext(tk.frame): def __init__(self, *args, **kwargs): tk.frame.__init__(self, *args, **kwargs) self.settings = self.settings() self.linenumbers = none self.text = customtext(self) self.vsb = tk.scrollbar(orient="vertical", command=self.text.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.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.focus() self.text.pack(side="right", fill="both", expand=true) def hide(self,event=none): if not self.settings.hide_linenumbers: self.settings.hide_linenumbers = true self.linenumbers.pack_forget() self.linenumbers = none 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") self.settings.hide_linenumbers = false 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() top_frame = tk.frame(root) text = linedtext(top_frame) text.pack(expand=1, fill="both") top_frame.pack(side="top", expand=1, fill="both") bottom_frame = tk.frame(root) button = tk.button(bottom_frame, text="hide", command=text.hide) button.pack(side="right") button = tk.button(bottom_frame, text="show", command=text.show) button.pack(side="right") bottom_frame.pack(side="bottom", fill="x") root.mainloop()
Comments
Post a Comment