Tkinter:按下时出现文本突出显示但接下来消失
Tkinter : Text highlight appears while pressed but disappear next
我最近一直在开发一个使用文本小部件显示字符串列表的 Tkinter (Python) 项目,但我 运行 遇到了一个我无法解决的问题:
启动时,我希望突出显示第一行,当我单击 up/down 箭头时,突出显示 up/down,作为选择栏。
我成功地做到了这一点,但问题是只有按下箭头时才会出现突出显示,而当它们被释放时,它就会消失。我希望它即使在我没有按任何键时也能保持不变。
这是我的代码:
class Ui:
def __init__(self):
# the list I want to display in Text
self.repos = repos
# here is the entry keys are bind to
self.entry = Entry(root)
self.entry.pack()
self.bind('<Up>', lambda i: self.changeIndex(-1))
self.bind('<Down>', lambda i: self.changeIndex(1))
# here is the Text widget
self.lists = Text(root, state=NORMAL)
self.lists.pack()
# inits Text value
for i in self.repos:
self.lists.insert('insert', i + '\n')
self.lists['state'] = DISABLED
# variable I use to navigate with highlight
self.index = 0
self.lists.tag_add('curr', str(self.index) + '.0', str(self.index + 1) + '.0') # added + '.0' to make it look '0.0' instead of '0'
self.lists.tag_config('curr', background='#70fffa', background='#000000')
self.root.mainloop()
def changeIndex(self, n):
# error gestion (if < 0 or > len(repos), return)
self.lists.tag_delete('curr')
self.lists.tag_add('curr', str(self.index) + '.0', str(self.index + 1) + '.0')
self.index = self.index + n
# to make it scroll if cannot see :
self.lists.see(str(self.index) + '.0')
我在 Stack 上没有看到任何类似的问题,所以我问了,但如果它是重复的,请不要犹豫告诉我。
你们能帮帮我吗?谢谢!
编辑:如果您想尝试一下,这里是完整的代码:https://github.com/EvanKoe/stack_tkinter.git
EDIT :我将 main.py 文件(调用 ui.py 的“后端”文件)添加到演示存储库。这样,您就可以 运行 项目(注意,main.py 中有“YOUR TOKEN”和“YOUR ORGANIZATION”字符串,您必须使用自己的 token/organization。我无法推送我的,否则 Github 会要求我删除我的令牌)
以下代码应该符合您的预期。代码下面的解释
from tkinter import *
repos = ["one","two","three","four"]
class Ui:
def __init__(self, parent):
# the list I want to display in Text
self.repos = repos
# here is the entry keys are bind to
self.entry = Entry(parent)
self.entry.pack()
self.entry.bind('<Up>', lambda i: self.changeIndex(-1))
self.entry.bind('<Down>', lambda i: self.changeIndex(1))
# here is the Text widget
self.lists = Text(parent, state=NORMAL)
self.lists.pack()
# inits Text value
for i in self.repos:
self.lists.insert('insert', i + '\n')
self.lists['state'] = DISABLED
# variable I use to navigate with highlight
self.index = 1
self.lists.tag_add('curr', str(self.index) + '.0', str(self.index + 1) + '.0') # added + '.0' to make it look '0.0' instead of '0'
self.lists.tag_config('curr', background='#70fffa', foreground='#000000')
def changeIndex(self, n):
print(f"Moving {n} to {self.index}")
self.index = self.index + n
self.index = min(max(self.index,0),len(self.repos))
self.lists.tag_delete('curr')
self.lists.tag_config('curr', background='#70fffa', foreground='#000000')
self.lists.tag_add('curr', str(self.index) + '.0', str(self.index + 1) + '.0')
# to make it scroll if cannot see :
self.lists.see(str(self.index) + '.0')
root = Tk()
ui = Ui(root)
root.mainloop()
对您的代码进行少量更改
- 更改了
Ui
函数以接受父 tk 对象作为参数
- 已将
self.index
初始化为 1 而不是 0,因为文本框的第一行是 1 而不是 0
- 将Up/Down键绑定到输入框。不确定为什么这是你想要的,但这似乎是你的评论所表明的
- 添加了一些检查代码以将索引值限制在 1 和 len(repos) 之间
- 自从您删除标签后每次设置时都重新创建标签样式(这就是它未显示的原因)
我建议您将 up/down 按钮绑定到文本框而不是输入框。必须 select 一个空白的输入框来在列表中上下滚动似乎有点奇怪。
此外,您为什么不直接使用内置的 Tkinter 列表小部件?
我终于设法解决了问题,这是由于我的事件绑定。我决定(改善用户体验)在顶部条目上绑定 up/down 箭头,而不是在文本小部件上绑定 em。我绑定了 4 个事件:
- 向上箭头 => 向上移动突出显示,
- 向下箭头 => 向下移动突出显示,
- Return 键 => 调用 get_name(),一个 returns 所选选项的函数,
- Any other Key => calls repo_filter(),该函数根据在条目中键入的内容更新文本小部件中显示的选项。
问题是按下 up/down 箭头会触发“up/down 键”事件和“任何其他键”事件,因此在刷新文本值后突出显示被移除。
为了解决这个问题,我只需要在“任何其他键”事件回调中验证按下的键既不是向上箭头也不是向下箭头:
def repo_filter(evt):
if evt.keysym == 'Up' or evt.keysym == 'Down': # verify that pressed key
return # isn't '<Down>' or '<Up>'
# filter Text widget
另外,很抱歉我一开始没有给你所有的代码,因为,你确实猜不到那些事件绑定。
感谢所有帮助过我的人!
我最近一直在开发一个使用文本小部件显示字符串列表的 Tkinter (Python) 项目,但我 运行 遇到了一个我无法解决的问题: 启动时,我希望突出显示第一行,当我单击 up/down 箭头时,突出显示 up/down,作为选择栏。 我成功地做到了这一点,但问题是只有按下箭头时才会出现突出显示,而当它们被释放时,它就会消失。我希望它即使在我没有按任何键时也能保持不变。
这是我的代码:
class Ui:
def __init__(self):
# the list I want to display in Text
self.repos = repos
# here is the entry keys are bind to
self.entry = Entry(root)
self.entry.pack()
self.bind('<Up>', lambda i: self.changeIndex(-1))
self.bind('<Down>', lambda i: self.changeIndex(1))
# here is the Text widget
self.lists = Text(root, state=NORMAL)
self.lists.pack()
# inits Text value
for i in self.repos:
self.lists.insert('insert', i + '\n')
self.lists['state'] = DISABLED
# variable I use to navigate with highlight
self.index = 0
self.lists.tag_add('curr', str(self.index) + '.0', str(self.index + 1) + '.0') # added + '.0' to make it look '0.0' instead of '0'
self.lists.tag_config('curr', background='#70fffa', background='#000000')
self.root.mainloop()
def changeIndex(self, n):
# error gestion (if < 0 or > len(repos), return)
self.lists.tag_delete('curr')
self.lists.tag_add('curr', str(self.index) + '.0', str(self.index + 1) + '.0')
self.index = self.index + n
# to make it scroll if cannot see :
self.lists.see(str(self.index) + '.0')
我在 Stack 上没有看到任何类似的问题,所以我问了,但如果它是重复的,请不要犹豫告诉我。
你们能帮帮我吗?谢谢!
编辑:如果您想尝试一下,这里是完整的代码:https://github.com/EvanKoe/stack_tkinter.git
EDIT :我将 main.py 文件(调用 ui.py 的“后端”文件)添加到演示存储库。这样,您就可以 运行 项目(注意,main.py 中有“YOUR TOKEN”和“YOUR ORGANIZATION”字符串,您必须使用自己的 token/organization。我无法推送我的,否则 Github 会要求我删除我的令牌)
以下代码应该符合您的预期。代码下面的解释
from tkinter import *
repos = ["one","two","three","four"]
class Ui:
def __init__(self, parent):
# the list I want to display in Text
self.repos = repos
# here is the entry keys are bind to
self.entry = Entry(parent)
self.entry.pack()
self.entry.bind('<Up>', lambda i: self.changeIndex(-1))
self.entry.bind('<Down>', lambda i: self.changeIndex(1))
# here is the Text widget
self.lists = Text(parent, state=NORMAL)
self.lists.pack()
# inits Text value
for i in self.repos:
self.lists.insert('insert', i + '\n')
self.lists['state'] = DISABLED
# variable I use to navigate with highlight
self.index = 1
self.lists.tag_add('curr', str(self.index) + '.0', str(self.index + 1) + '.0') # added + '.0' to make it look '0.0' instead of '0'
self.lists.tag_config('curr', background='#70fffa', foreground='#000000')
def changeIndex(self, n):
print(f"Moving {n} to {self.index}")
self.index = self.index + n
self.index = min(max(self.index,0),len(self.repos))
self.lists.tag_delete('curr')
self.lists.tag_config('curr', background='#70fffa', foreground='#000000')
self.lists.tag_add('curr', str(self.index) + '.0', str(self.index + 1) + '.0')
# to make it scroll if cannot see :
self.lists.see(str(self.index) + '.0')
root = Tk()
ui = Ui(root)
root.mainloop()
对您的代码进行少量更改
- 更改了
Ui
函数以接受父 tk 对象作为参数 - 已将
self.index
初始化为 1 而不是 0,因为文本框的第一行是 1 而不是 0 - 将Up/Down键绑定到输入框。不确定为什么这是你想要的,但这似乎是你的评论所表明的
- 添加了一些检查代码以将索引值限制在 1 和 len(repos) 之间
- 自从您删除标签后每次设置时都重新创建标签样式(这就是它未显示的原因)
我建议您将 up/down 按钮绑定到文本框而不是输入框。必须 select 一个空白的输入框来在列表中上下滚动似乎有点奇怪。
此外,您为什么不直接使用内置的 Tkinter 列表小部件?
我终于设法解决了问题,这是由于我的事件绑定。我决定(改善用户体验)在顶部条目上绑定 up/down 箭头,而不是在文本小部件上绑定 em。我绑定了 4 个事件:
- 向上箭头 => 向上移动突出显示,
- 向下箭头 => 向下移动突出显示,
- Return 键 => 调用 get_name(),一个 returns 所选选项的函数,
- Any other Key => calls repo_filter(),该函数根据在条目中键入的内容更新文本小部件中显示的选项。
问题是按下 up/down 箭头会触发“up/down 键”事件和“任何其他键”事件,因此在刷新文本值后突出显示被移除。
为了解决这个问题,我只需要在“任何其他键”事件回调中验证按下的键既不是向上箭头也不是向下箭头:
def repo_filter(evt):
if evt.keysym == 'Up' or evt.keysym == 'Down': # verify that pressed key
return # isn't '<Down>' or '<Up>'
# filter Text widget
另外,很抱歉我一开始没有给你所有的代码,因为,你确实猜不到那些事件绑定。
感谢所有帮助过我的人!