在 Tkinter 文本中设置标签 - 尽管有进一步的变化,标签的范围始终以 1.1 开头



在我的Tkinter GUI中,我试图创建一个功能,用户可以在其中逐字逐句地重写输入小部件中的给定文本。如果单词写得正确与否,文本的颜色应该根据实际情况而改变。问题是,我创建的标签范围总是以1.1开头,尽管我将开头设置为每个单词中第一个字母的位置"例如,在我使用空格键两次后,文本中的第二个单词从字符串中的位置10开始:text.tag_ranges(tag_name)返回(<string object: '1.1'>, <string object: '1.15'>),但当我print(start)时,它给了我期望的:1.10";。结果是,着色总是从文本的开头开始,而不是从单词开始。结局总是好的。是不是出了什么我看不见的问题?

import tkinter as tk
import re
t = "quae ab illo inventore veritatis et quasi"
text_split = t.split()
last_char = len(t)
whitespaces_list = [0] + [i.start() for i in re.finditer(" ", t)] + [last_char]
window = tk.Tk()
window.geometry('750x600')
n = 0

def next_word(event):
global n
n = n + 1
z = text_split[n - 1]
correct_word = re.search(z, entry.get())
if n < len(whitespaces_list):
start = '1.' + str(whitespaces_list[n - 1])
end = '1.' + str(whitespaces_list[n])
for x in range(len(text_split) - 1):
text.tag_add(str(x), start, end)
# print(text.tag_ranges(str(x)))
# print(start)
# print(end)
if correct_word:
text.tag_config(str(x), foreground="green")
else:
text.tag_config(str(x), foreground="red")
entry.delete(0, tk.END)

label1 = tk.Label(width=200, height=10)
label1.pack()
text = tk.Text(label1)
text.place(x=40, y=20)
text.insert(tk.INSERT, t)
label2 = tk.Label(height=80, width=200)
label2.pack()
entry = tk.Entry(label2)
entry.place(x=300, y=20)
window.bind("<space>", next_word)
window.mainloop()

此代码演示如何使用Text搜索、tag_configtag_add

我通过Control-L包含了一个文件对话框文本加载程序

Entry对象用于搜索单词或短语。如果找到,它们都会高亮显示,结果会按名称(str(和位置(list(存储在字典findstore中。


import os
import tkinter as tk
from tkinter import filedialog as fido
def flexx( o, r = 0, c = 0, rs = 1, cs = 1 ):
if r != None:
o.rowconfigure( r, weight = rs )
if c != None:
o.columnconfigure( c, weight = cs )
findstore = dict( name = '', place = [] )
window = tk.Tk()
flexx( window )
label = tk.LabelFrame( window, labelanchor = tk.N, text = "Banner" )
label.grid( row = 0, column = 0, sticky = tk.NSEW )
flexx( label )
text = tk.Text(
label, undo = 1, takefocus = 1,
font = "Consolas 10 normal", wrap = tk.NONE )
text.grid( row = 0, column = 0, sticky = tk.NSEW )
scroll = tk.Scrollbar( window, orient = tk.VERTICAL, command = text.yview )
scroll.grid( row = 0, column = 1, sticky = tk.NS )
text[ 'yscrollcommand' ] = scroll.set
entry = tk.Entry(
window, width = 20, takefocus = 1, font = "Consolas 20 normal" )
entry.grid( row = 1, column = 0, columnspan = 2, sticky = tk.EW )
window.update_idletasks( )
t = "quae ab illo inventore veritatis et quasin" + "nn".join( dir( text ) )
text.insert( tk.INSERT, t )

def closer( ev ):
window.destroy( )
def banner( n ):
label[ "text" ] = f"{n}"
def find( k, color = "#00eeee" ):
"""search from the beginning"""
global i
p = "1.0"
i = [ ]
ln = len( k )
if len( k ) > 0:
# use text search
while 1:
p = text.search( k, p, stopindex="end" )
if p == "":
break
i.append( p )
p += "+1c"
if i:
p = i[ 0 ]
if "" in i:
i.remove( "" )
banner( f"Found( {len(i)} )" )
# use color as tagname
if len( i ) > 0:
text.tag_delete( color )
text.tag_config( color, foreground = color, font = "Consolas 12 bold" )
findstore.update( name = k, place = i )
for a in i:
text.tag_add( color, a, f"{a}+{ln}c" )
def next_word( ev ):
word = entry.get( )
entry.delete( 0, tk.END )
# search for word|phrase
find( word )
# Store results in findstore
print( findstore[ 'name' ], findstore[ 'place' ] )
def loadfile( ev ):
pathfilename = fido.askopenfilename( title = "Choose a text file" )
if os.path.exists( pathfilename ):
with open( pathfilename, mode = 'rt' ) as loader:
info = loader.read()
text.delete( '1.0', 'end' )
text.insert( '1.0', info )
text.edit_reset( )
banner( os.path.split( pathfilename )[ 1 ] )
entry.bind( "<Return>", next_word )
window.bind( "<Escape>", closer )
window.bind( "<Control-L>", loadfile )
entry.focus_set()
window.mainloop()    

最后我找到了一个非常简单的解决方案,我错误地设置了循环,它应该被删除,正确的代码部分是:

if n < len(whitespaces_list):
start = '1.' + str(whitespaces_list[n - 1])
end = '1.' + str(whitespaces_list[n])
text.tag_add(str(n), start, end)
if correct_word:
text.tag_config(str(n), foreground="green")
else:
text.tag_config(str(n), foreground="red")

谢谢Derek和Matiss的回复。

最新更新