python3-tkinter中的只读文本小部件;跨平台

时间:2011-10-16 05:09:20

标签: python text python-3.x tkinter readonly

如何抑制最终用户在文本小部件中编辑/添加/删除文本的能力? (Python v3.2 ..和tkinter)

重点是仅抑制更改/添加/删除文本的能力,而不是强制转换其他功能。也许NoEdit Text widged可能是一个更好的名字。

我已经尝试 .text ['state'] ='禁用',它在Windows中几乎 OK(它仍允许用户选择/复制文字高亮显示)选择,向上/向下翻页和向上/向下按钮工作。唯一被破坏的东西似乎是光标变得不可见。)

但在MacIntosh上,一切都破了。没有亮点,没有选择/复制,... UGH

由于Tkinter几乎没有Python文档,我搜索并找到了一些TCL建议,派生一个新类并禁止插入删除函数。 / p>

所以,我已经尝试过了:

class roText(tk.Text):
    def insert(self,*args,**kwargs):
        print(" Hey  - Im inside roText.insert")
        pass
    def delete(self,*args,**twargs):
        pass    
    def pInsert(self,*args,**twargs):
        super().insert(*args,**twargs)

不幸的是它无法正常工作。显然 tkinter在最终用户输入/删除代码时不使用那些插入和删除功能。也许那些TCL插入/删除是别的,我在TCL和斯瓦希里语的翻译中丢失了一些东西。 tkinter.Text用于最终用户编辑文本的功能是什么?希望他们不是内部的......

那么,有没有办法修改Text小部件以仅抑制最终用户编辑? 有没有办法在没有潜入内部并覆盖内部Tkinter代码的情况下执行此操作,因此下一版Tkinter不会破坏这些内容?

查看Idle shell窗口,我发现他们已设法禁止编辑(最后一行除外)。所以有一种方法。但它是什么以及成本如何?

3 个答案:

答案 0 :(得分:3)

很抱歉碰到一个老问题,但我也在寻找这个问题的答案,最后找到了解决方案。我发现的解决方案涉及在文本小部件具有焦点时重写键绑定并且非常简单。找到here

要覆盖小部件的绑定,有一个绑定函数,您可以在其中传递要覆盖的字符串以及您希望它调用的新函数。

    self.txtBox.bind("<Key>", self.empty)

在类中的其他地方,您需要定义处理事件的函数。

    def empty(self, event):
        return "break"

通过返回字符串“break”,事件处理程序知道在函数之后停止,而不是继续执行默认操作。

我希望这能回答你的问题。欢呼声。

答案 1 :(得分:2)

disabled状态似乎无法在Mac上运行的原因是因为它关闭了为窗口小部件提供焦点的绑定。如果没有焦点,Mac上的突出显示就不会显示出来。如果您将状态设置为disabled,然后将绑定分配给<ButtonPress-1>以将焦点显式设置为禁用的文本小部件,则可以选择并复制文本,并突出显示。

至于光标消失......可以说,这就是应该发生的事情。光标告诉用户“这是插入文本的位置”。由于不会插入任何文本,因此具有该视觉线索会使用户感到困惑。如果真的很重要的话,你可以做的是在他们点击的任何地方插入一个小图像来模拟光标。

回答关于窗口小部件是否实际使用insertdelete方法的问题:实际底层窗口小部件上的方法是默认绑定使用的方法,因此在子类中覆盖它们没有任何效果。您需要重做所有默认绑定才能工作。这是可行的,但很多工作。

不幸的是,这是Tcl编程真正发挥作用的一个领域,因为你可以简单地禁用小部件的insertdelete命令。当然,你可以直接在Tkinter中做到这一点,因为最终它运行tcl代码来完成所有事情,但是这将涉及编写一些tcl代码,从Python编码器的角度来看这不是一个非常好的解决方案。

我认为最好的解决方案是使用禁用状态,然后添加足够的绑定来执行您想要的操作。

这是一个简单的示例,通过明确设置焦点鼠标按钮单击来工作。使用此代码,我可以单击并滑动以选择区域,或者双击或三击以选择单词和行:

import Tkinter as tk

class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.text = tk.Text(width=40, height=20)
        self.text.bind("<1>", self.set_focus)
        self.text.insert("end", "\n".join(dir(tk.Tk)))
        self.text.configure(state="disabled")
        self.text.pack(fill="both", expand=True)

    def set_focus(self, event):
        '''Explicitly set focus, so user can select and copy text'''
        self.text.focus_set()

if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

答案 2 :(得分:-1)

@BryanOakley我花了一段时间来测试你的建议,因为我没有Mac。 不幸的是,Mac的Python实现是错误的。 我添加了焦点,即我在创建窗口并插入文本后调用的禁用功能,现在先调用:

self.txt['state'] = 'disabled'

然后

self.txt.focus_set()

我认为你的建议是什么。

它“有点”有效。即:在选择文本(单击并拖动或双击)时,突出显示当时大多数的作品。 Python必须有一些不良内存引用或此类错误:有时突出显示最初不起作用,然后在更多单击后开始工作(在同一窗口中)。有时,当调用程序时,它对蝙蝠起作用。有时用Shift-rightArrow键进行选择会有效,但用鼠标选择则不行。然后再开始工作。或者它可以在一个窗口中正常工作,但不能在另一个窗口中工作(两个都是同一个类),然后开始在所有窗口中工作......等等......

好处是添加焦点并不会严重影响Windows(即一切正常,因为没有焦点。 我想在这一点上我只希望Python for Mac的未来/下一版本能够修复这些错误..

顺便说一下,似乎Mac对于Python来说有点孤儿。对于Windows来说,实现起来更加丑陋。我的意思是字体看起来更糟糕,按钮等等。或者它可能是由于不同的屏幕分辨率和Python端口不能很好地解释那些。不确定

反正。感谢您的帮助和建议,将焦点用于Mac。