簡體   English   中英

如何使 tkinter 文本小部件無法選擇?

[英]How can I make a tkinter text widget unselectable?

我想讓我的 tkinter Text只是一個輸出而不是一個輸入。 通過一些研究,我發現text.config(state="disabled")禁用了用戶輸入,但它仍然允許選擇我不想要的文本。

如何讓我的Text小部件不可選擇和不可寫?

最簡單的方法是替換支持選擇的默認文本綁定,以便它們什么都不做。 有幾種方法可以做到這一點:使用綁定標簽可以刪除所有默認綁定,或者您可以只刪除默認綁定子集的綁定。

刪除所有默認綁定

小部件上的所有綁定——包括默認綁定——都與綁定標簽(也稱為“綁定標簽”)相關聯。 文本小部件的綁定標簽是“Text”,文本小部件的所有默認綁定都與此標簽相關聯。 如果刪除該綁定標記,則會刪除所有特定於文本的綁定。

任何小部件的默認綁定標簽是小部件的字符串表示、內部小部件類(在本例中為“Text”)、頂級窗口的內部名稱(在本例中為 root)和特殊窗口的元組標記“全部”。

在下面的示例中,我們更改了綁定標簽,以便不包含“Text”,從而有效地刪除了文本小部件上的所有默認綁定:

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")

這種方法的缺點是您必須弄清楚與選擇機制相關的所有綁定是什么。 另一方面,它使您可以完全控制每個按鍵或按鈕的作用。

一個只讀的、不可選擇的文本小部件。

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 上測試

我相信您必須用另一個小部件(例如LabelLabelFrame替換它才能完成此操作。 您也可以使用from tkinter import messagebox並在另一個窗口(如信息窗口或錯誤消息窗口)中彈出您想要的文本。 我認為就Text小部件而言,不幸的是,將狀態設置為禁用是您可以為您的目的所做的最好的事情,盡管用戶無法編輯它,但仍可以復制該文本。

當您只希望文本小部件是禁用且不可選擇的普通日志時,這是防止選擇/突出顯示文本的最簡單方法。

當我遇到這個問題時,我想我只需要將一些文本配置屬性(highlightbackground、highlightcolor 或 selectbackground)設置為“黑色”。 沒有任何效果。 Text 小部件使用可用於標記控件內的 Text 的標簽。 用戶定義標簽以及特殊標簽“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”

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM