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

另外,很抱歉我一开始没有给你所有的代码,因为,你确实猜不到那些事件绑定。

感谢所有帮助过我的人!