如何使Tkinter文本小部件不可选择?

时间:2019-02-20 18:00:00

标签: python tkinter

我希望使tkinter Text仅作为输出而不是输入。通过一些研究,我发现text.config(state="disabled")禁用了用户输入,但仍允许选择文本,这是我不希望的。

如何使我的Text小部件不可选择和不可写?

4 个答案:

答案 0 :(得分:1)

最简单的方法是替换支持选择的默认文本绑定,以使它们不执行任何操作。有两种方法可以执行此操作:使用绑定标签可以删除所有默认绑定,也可以仅将默认绑定的子集删除。

删除所有默认绑定

小部件上的所有绑定(包括默认绑定)都与绑定标签(也称为“ bindtags”)相关联。文本窗口小部件的绑定标签是“文本”,并且文本窗口小部件的所有默认绑定都与此标签关联。如果删除该绑定标签,则将删除所有特定于文本的绑定。

任何窗口小部件的默认绑定标签是该窗口小部件的字符串表示形式的元组,内部窗口小部件类(在这种情况下为“文本”),顶级窗口的内部名称(在这种情况下为root),和特殊标签“ all”。

在下面的示例中,我们更改了绑定标记,以便不包括“文本”,从而有效地删除了文本小部件上的所有默认绑定:

import tkinter as tk

root = tk.Tk()
text = tk.Text(root)
text.bindtags((str(text), str(root), "all"))

删除特定的绑定

如果您希望保留一些默认绑定,则可以仅替换不需要的绑定。您可以通过创建自己的绑定并让这些绑定返回字符串“ break”来实现。这个特殊的返回值告诉tkinter停止进一步处理该事件。

例如,要防止双击选择光标下的单词,可以执行以下操作:

text.bind("<Double-1>", lambda event: "break")

此方法的缺点是您必须弄清楚与选择机制相关的所有绑定是什么。另一方面,它使您可以完全控制每个按键或按钮的功能。

答案 1 :(得分:1)

一个不可选择的只读文本小部件。

class Textarea(tkinter.Text):
  def __init__(self, master, **kw):
    super().__init__(master, **kw)
    # disable text alteration
    self.configure(state="disabled")
    # untag any selection from beginning to end
    def unselect(event):
      self.tag_remove("sel", "1.0", "end")
    # catch different ways selections could be made and unselect before copying or cutting
    good = ["<ButtonRelease-1>", "<Leave>", "<Control-c>", "<Control-C>", "<Control-x>", "<Control-X>"]
    better = good + ["<Shift-Left>", "<Shift-Up>", "<Shift-Right>", "<Shift-Down>", "<Shift-Home>", "<Shift-End>", "<Shift-Next>", "<Shift-Prior>"]
    excessive = better + ["<Shift-KP_1>", "<Shift-KP_2>", "<Shift-KP_3>", "<Shift-KP_4>", "<Shift-KP_6>", "<Shift-KP_7>", "<Shift-KP_8>", "<Shift-KP_9>"]
    for sequence in better:
      self.bind(sequence, unselect, add="+")
    # remove the appearance of selection
    self.configure(selectforeground=self.cget("foreground"), selectbackground=self.cget("background"))
    # disallow export of selection in case anything gets through
    self.configure(exportselection=False)

在python 3.8.2上测试

答案 2 :(得分:0)

我相信您必须将其替换为另一个小部件,例如LabelLabelFrame才能完成此操作。同样,您可以使用from tkinter import messagebox并在另一个窗口(例如信息窗口或错误消息窗口)中弹出想要的文本。我认为,就Text小部件而言,不幸的是,将状态设置为Disabled是您可以为达到目的而做的最好的事情,尽管无法编辑,用户仍可以复制该文本。

答案 3 :(得分:0)

这是防止文本被选中/突出显示的最简单方法,当您只希望“文本”小部件成为禁用和无法选择的普通日志时即可。

遇到问题时,我认为只需要将一些Text配置属性(highlightbackground,highlightcolor或selectbackground)设置为“ Black”即可。没事。文本小部件使​​用可用于在控件中标记文本的标签。用户定义标签以及特殊标签“ sel”的配置具有许多设置,包括前景(颜色)和背景(颜色)。

tag_config(“ sel”,background =“ black”)

太容易了吧?那也不行。

事实证明,突出显示实际上是覆盖在文本上的位图。这由标记的bgstipple(位图)配置控制。文档指出可以使用许多系统位图(灰色阴影),但是也可以指定自己的位图。位图必须是xbm,并且由于它是文本文件,因此很容易创建自己的位图。

将以下内容放入名为transparent.xbm的文件中。

#define trans_width 2
#define trans_height 2
static unsigned char trans_bits[] = {
   0x00, 0x00
};

这是...

class TextLog(tk.Text):         
    def __init__(self, *args, **kwargs):  
        super().__init__(*args, **kwargs)
        self.tag_config("sel", bgstipple="@transparent.xbm", 
                                                       foreground="white")
        self.config(state="disabled")

    def write_log(self, text="", clear=False)
        self.configure(state='normal')

        if clear is True:
            self.delete("1.0","end")

        self.insert(tk.END, text)
        self.see(tk.END)
        self.config(state="disabled")

根据.xbm相对于使用TextLog的模块的位置,您可能需要在其前面加上路径“ @ path / to / transparent.xbm”