I basically got the unwanted characters removed from the Text widget, but when I hit a line break and try to scroll the text with the keyboard or mouse, I just can't (it always stays in the same place). this is done in the "validate text" method
class NewNewsFrame(Frame):
def __init__(self, parent):
self.Parent = parent
self.initializecomponents()
pass
def validate_text(self, widger):
value = widger.get("1.0", "end-1c")
print value.fon
if not value.isalnum():
var = str()
for i in value:
print(f"({i})")
var = i if(i.isalpha() or i.isdigit() or i == "(" or i == ")" or i == " " or i == "," or i == "." or i == "\n")else ""
widger.delete("1.0", "end-1c")
widger.insert("end-1c", var)
pass
def initializecomponents(self):
Frame.__init__(self, self.Parent)
self.DescriptionLabel = Label(self)
self.DescriptionBox = Text(self)
# DescriptionLabel
self.DescriptionLabel.config(text="Description of the news:",bg=self["bg"], fg="#FFFFFF", font="none 15",anchor="nw")
self.DescriptionLabel.place(relwidth=1, relheight=0.1, relx=0, rely=0.11, anchor="nw")
# DescriptionBox
self.DescriptionBox.bind("<KeyPress>", lambda event: self.validate_text(self.DescriptionBox))
self.DescriptionBox.bind("<FocusOut>", lambda event: self.validate_text(self.DescriptionBox))
self.DescriptionBox.place(relheight=0.4, relwidth=1, relx=0, rely=0.16, anchor="nw")
pass
I tried to find how keyboard scrolling works, but I still don't know how to do it
CodePudding user response:
The problem is that you're deleting and restoring all of the text with every keypress. This causes the cursor position to change in unexpected ways that breaks the default bindings.
If you're wanting to prevent certain characters from being entered, there's a better way. If your validation function returns the string "break", that prevents the character from being inserted. You don't have to re-scan the entire contents or delete and restore the text, because the bad characters never get entered in the first place.
Your validation function might look something like this:
def validate_text(self, event):
if event.char.isalpha() or event.char.isdigit() or event.char in "() ,.\n":
pass
else:
return "break"
Next, simplify the binding to look like the following. Tkinter will automatically pass the event
parameter to the function.
self.DescriptionBox.bind("<KeyPress>", self.validate_text)
This will break your <FocusOut>
binding, but I'm not sure it's needed.
For more information about how events are processed and why returning "break" does what it does, see this answer to the question Basic query regarding bindtags in tkinter. That question is about an Entry
widget but the concept is the same for all widgets.