【问题标题】:Tkinter : Text highlight appears while pressed but disappear nextTkinter:按下时出现文本突出显示但接下来消失
【发布时间】:2021-12-10 19:09:21
【问题描述】:

我最近一直在开发一个 Tkinter (Python) 项目,该项目使用 Text 小部件显示字符串列表,但遇到了一个我无法解决的问题: 在启动时,我希望第一行突出显示,当我单击向上/向下箭头时,突出显示向上/向下,作为选择栏。 我成功地做到了,但问题是突出显示仅在按下箭头时出现,而当它们被释放时,它会消失。即使我不按任何键,我也希望它保持不变。

这是我的代码:

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

编辑:我将 main.py 文件(调用 ui.py 的“”“后端”“”文件)添加到演示存储库。这样,您就可以运行项目(请注意,main.py 中有“YOUR TOKEN”和“YOUR ORGANIZATION”字符串,您必须使用自己的令牌/组织进行修改。我无法推送我的或 Github 会要求我删除我的令牌)

【问题讨论】:

  • 您的代码无法运行,因为Ui 不是小部件,并且您在__init__() 中调用了self.bind(...)self.root 也未定义。
  • Ofc 我定义了self.root、Ui 和你说的所有这些东西,我只是没有在这里输入它们以简化帖子。此外,代码运行良好(只是 UI/UX 改进)
  • 如果没有minimal reproducible example,我们如何提供帮助?
  • 我刚刚发布了一个包含完整文件的 github 链接 :)
  • 您不应该使用tag_delete(),因为它会删除与标签相关的所有内容,包括配置的颜色。请改用tag_remove()

标签: python tkinter text tags highlight


【解决方案1】:

我终于设法解决了这个问题,这是由于我的事件绑定。我决定(改进用户体验)在顶部条目上绑定向上/向下箭头,而不是在文本小部件上绑定 em。我绑定了 4 个事件:

  • 向上箭头 => 向上移动突出显示,
  • 向下箭头 => 向下移动突出显示,
  • 返回键 => 调用 get_name(),一个返回所选选项的函数,
  • 任何其他 Key => 调用 repo_filter(),该函数根据条目中输入的内容更新 Text 小部件中显示的选项。

问题在于按下向上/向下箭头会触发“向上/向下键”事件和“任何其他键”事件,因此在刷新 Text 值后高亮已被移除。

为了解决这个问题,我只需要在“任何其他键”事件回调中验证按下的键既不是向上箭头也不是向下箭头:

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

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

感谢所有试图帮助我的人!

【讨论】:

    【解决方案2】:

    以下代码应该符合您的预期。代码解释如下

    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
    • 将向上/向下键绑定到输入框。不知道为什么这是你想要的,但这似乎是你的 cmets 所指示的
    • 添加了一些检查代码以将索引值限制在 1 和 len(repos) 之间
    • 自从您删除标签后,每次设置标签样式时都会重新创建它(这就是它没有显示的原因)

    我建议您将向上/向下按钮绑定到文本框而不是输入框。必须选择一个空白输入框才能在列表中上下滚动似乎有点奇怪。

    另外,你为什么不只使用 Tkinter 列表小部件中的构建?

    【讨论】:

    • 嘿!非常感谢您的回答!遗憾的是,它对我不起作用...我将向上/向下箭头绑定到该条目,因为我将此条目的焦点放在启动上,并且在能够使用箭头之前将焦点设置在 Text 小部件上真的很烦人.我从另一个 python 程序中使用这个类(Ui),这就是为什么我在 init 函数中做所有事情(我用 (from ui import Ui, variable = Ui(repos).get_name() 调用它) , get_name() 是返回高亮文本的函数)
    • 这就是为什么你通常应该提供一个最小的、可执行的例子。通过遗漏重要的代码部分,我创建了一个不适用于您非常具体的用例的答案(这不是一个好方法)。我相信这可以解决您突出显示的问题,您可能只需稍微修改代码即可将其集成到您的其余代码中。
    • 顺便说一句,直接从Tk继承不是更好吗?或至少Frame?因为这将允许使用 self 作为父级并提供继承的方法
    • @Matiiss 我同意你的看法。有更好的方法来创建它。我试图修复突出显示的问题,但必须修复其他问题才能使其独立工作。
    • 我已经说过了,但是我在顶部有一个专注于启动的条目,并且我希望能够在输入时使用箭头。将箭头绑定到 Text 小部件意味着用户必须停止键入,然后用鼠标单击 Text 以使其获得焦点,然后使用箭头选择他想要的那个。从我的角度来看,这是一个非常糟糕的 UX 实现,这就是我将它绑定到 entry 的原因。
    猜你喜欢
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    • 1970-01-01
    • 2016-01-09
    • 2017-05-15
    • 2014-11-26
    • 2018-07-30
    • 1970-01-01
    相关资源
    最近更新 更多