我正在尝试以一种非常特定的方式来限制Python中的tkinter文本小部件或输入小部件(任何一种小部件类型都可以)中的字符数。我有一个关闭文本控件的解决方案:
string = self.text.get("1.0","end-1c")
if len(string) >= 5:
self.text.delete('1.0', "end-1c")
string = string[:-1]
self.quantity_entry.insert(END, string)
但是上面的代码执行以下操作:如果我输入123456,则将其内容转换为12346。它会截取现有字段的最后一个字符(5),然后将键入的最后一个字符(6)放在结束。这样就变成了12346。
我想要的是12345保留12345,这意味着现有的12345字符串应保持原样,并且任何新字符都将被阻止附加。有办法吗?
我尝试使用:
self.text.configure(state="disabled")
这确实阻止了后续字符的插入,因此12345保留为12345。但这将锁定该字段,以防将来进行编辑。即使随后尝试使用:
self.text.configure(state="normal")
该字段保持锁定状态。我希望用户如果达到五个字符的限制,就能够编辑该字段。
谢谢。
答案 0 :(得分:1)
跟踪变量将更加整洁。然后它甚至不会在屏幕上短暂闪烁。您可以将其打包为一个整洁的子类,如下所示:
<?php
session_start();
error_reporting(0);
$user=$_SESSION['user'];
$right=$_SESSION['right'];
if($user==true){
?>
答案 1 :(得分:0)
我想出了解决方案。在.bind方法中,我需要使用
"<KeyRelease>"
而不是
"<Key>"
然后,作为一个较小的编辑,> = 5需要更改为>5。现在可以使用了。当我输入123456时,它会非常短暂地在屏幕上显示123456,但是随后很快将其切掉6,因此它又回到了12345。是的!
答案 2 :(得分:0)
我知道这很旧,但我认为它可以帮助一些人。
一直在寻找一个非常优雅的解决方案来解决这个问题。但是还没有找到。所以我想我会发布我的凌乱的。
如果你觉得这有用,请投票,如果你对我如何更清晰地沟通有想法,我也很乐意。
这是“一个”答案。但是,如果您解释为什么选择编写您所做的代码会有所帮助,这样我就可以更好地指导您思考得出解决方案的方法。
# IMPORT MODULES AND ALIAS THEM
import tkinter as tk
# This is a place holder to self.quantity_entry.insert(END, string) just to
# simulate the call to some other object
def OtherTextWidget(string):
print( f"{text1.index(tk.END)}, {string}" )
# This is the 'meat' of your solution that limits the input
def Restrict(e=None):
print(e.type) # just to proof that we are pressing a key
# If for some unknown reason this function gets called on key-release, it will
# terminate the function. Because it will break our desired behavior.
if int(e.type) == 3:
return
# The 'widget.bind()' event argument pass a reference to the widget that
# called it. Se we use that here to get the text from the caller
# "text1.bind()" as event.widget.get() note we have aliased 'event' as 'e'
# inside the function space.
# Get text from start to the current end length minus the '\n' character
string = e.widget.get("1.0","end-1c")
# If there are 5 or more characters go ahead with the limit
# Note len() starts at 0, so 4<= is equal to 5+ chars
if 4 <= len(string):
# Get the first five characters before the delete
OtherTextWidget( e.widget.get("1.0","1.5") )
# !!NOTES!!
# We are lazy and don't want to code a rejection for a 6th character. So
# we overwrite the 5th character, the result is the same for less work.
# we are operating during the key press, and the 6th character is not
# inserted until the key release. The 5th character is empty if you
# debug it after the delete. Again the 5th character will be replaced
# by the 6th on the key release.
# delete the 5th character to the '\n', remember we are counting from 0.
e.widget.delete('1.4', "end-1c")
# TKINTER OBJECTS SETUP:
root = tk.Tk()
text1 = tk.Text(root, width=7, height=1) # 7 chars long, 1 char high
# We give the "entry box" 5 +2 extra character for aesthetics spacing.
# It just looks better with a little room to breath.
text1.pack() # fits the widget in the minimum space within the frame/window
text1.focus_set() # because I'm lazy and I want the cursor already in the widget.
# BIND TEXT WIDGET KEY INPUT EVENT:
# Whenever there is a key press inside the text widget this will fire the
# Restrict() function with the 'kepress event' argument
# That events data is in key:value pairs and looks something like this:
# <KeyPress event state=Mod1 keysym=1 keycode=97 char='1' x=1959 y=69>
text1.bind('<Key>', Restrict)
# start the tkinter event loop and open a toplevel window
root.mainloop()
# The '<Key>' gives a e.type of 2 or key press/down
# if you use '<KeyRelease>' it gives a e.type of 3 release/up and we will have to
# change some code around to make it work. But the important difference is it will
# place the 6th character in the field then delete it, that doesn't look crisp.
# This is why we are operating on a key press rather than release, because we want
# to operate on the string before the character is insert into the text widget.
为了清楚起见,这里是有限的注释代码。 (更新:我认为拥有实际显示的字符串会很好,因此添加了此发布切换来捕获它。)
import tkinter as tk
def OtherTextWidget(string):
print("Key Press Phase:", string)
# Solution - Step 1. toggle full flag
global full #(update)
full = False
# Solution - Step 4. profit
def AfterRestrict(e=None): #(update)
global full
if True == full:
OtherTextWidget( e.widget.get("1.0","1.5") )
print("Key Release Phase:", e.widget.get("1.0","1.5") )
# Solution - Step 3. limit input
def Restrict(e=None):
global full #(update)
string = e.widget.get("1.0","end-1c")
if 4 <= len(string):
e.widget.delete('1.4', "end-1c")
full = True #(update)
else: #(update)
full = False
root = tk.Tk()
text1 = tk.Text(root, width=7, height=1)
text1.pack()
text1.focus_set()
# Solution - Step 2. get input event from widget
text1.bind('<Key>', Restrict)
text1.bind('<KeyRelease>', AfterRestrict) #(update)
root.mainloop()
很抱歉我很累,但希望这对一些人有所帮助。 :)