是否有可能在Tkinter Text Widget(python)中使用自定义对象而不是字符串?

是否有可能在Tkinter Text Widget(python)中使用自定义对象而不是字符串?

问题描述:

我想创建一个文本编辑器,它将操纵像对象一样的字符串。理想情况下,我想继承Tkinter的Text Widget或其他一些Gui模块,以允许我替换此自定义对象而不是使用字符串。是否有可能在Tkinter Text Widget(python)中使用自定义对象而不是字符串?

我明白如何创建对象本身(本质上只是用元数据标记每个单词),但不知道如何操作呈现的对象作为文本,同时保留其他属性。

例如,
文本编辑器导入包含“Hello World”的文件。在打开这个文本时,两个单词都被标记了相关的属性。 (下面显示的字典,但理想的对象Hello.strContent,Hello.index等)

Hello={strContent: "Hello", index: 0, speaker: "Joe", paragraph: 3} 
World={strContent: "World", index: 1, speaker: "Joe", paragraph: 3} 

现在我完全虽然我怎么可能让这些字符串如可操作对象难倒,并受到切割,复制,粘贴,删除和重新排列,在文本gui中。我不需要程序允许我键入任何新词或创建新对象,只需操作转换打开的文件时已初始化的对象即可。

任何帮助或方向将不胜感激。谢谢。

+0

是不是有一个原因,你不能只是将'strContent'作为字符串添加到文本中,或者甚至引用字典中的每个对象?如在中,每个单词都是一个字典键,其中分配给该键的值是上面列出的字典? –

+0

我喜欢使用字典的想法,但源文本将包含相同单词的重复。例如,一个丑陋的解决方案将使用索引附加到每个单词的开头。
00和01here 02is 03a 04sample 05text 06whis 07is 08simple。
现在,假设我在我们假设的Gui编辑器中编辑了这段文字:
Acronomic

+0

您可以创建一个列表吗?将每个对象追加到列表中,然后遍历列表并将每个'strContent'添加到'text'小部件中? –

我认为你可以做这样的事情

class myobj: 
    def __init__(self, text): 
     self.strContent=text 
hello = [[myobj("Hello"), myObj("World")], [myobj("Paragraph"), myobj("2")]] 

那么每当你需要显示的文字,你会拥有它遍历像这样

printableStr = "" 
for paragraph in hello: 
    for word in paragraph: 
     printableStr += word.strContent + " " 
    printableStr += "\n" 

然后printableStr将是一个不错的包含来自你好的所有信息的字符串

+0

这绝对适用于显示文本,但我期望在文本显示后对其进行操作,并让每个单词仍保留其元数据。理想情况下,它可以在像app这样的文本编辑器中进行操作,但是操纵myObjs而不是字符串。 – Acronomic

注意:这试图回答被问到的问题,但我怀疑这是一个xy problem。在回答结束时,我会提出一些其他建议。


文本小部件不能有一些复杂的对象作为其基础数据结构。它可以显示文本,并且可以有与文本关联的标签。您也可以插入图片和小工具,但我认为这与您所问的无关。

在读取数据时,可以为每条元数据构造标签,并将这些标签与一定范围的文本相关联。例如,单词“你好”可能有标签“段落:3”,“扬声器:乔”和“索引:0”。 “世界是相似的,除了它会标记‘指数:1’

这会很容易在最初显示的数据做例如:。

data = [{"strContent": "Hello", "index": 0, "speaker": "Joe", "paragraph": 3}, 
     {"strContent": "World", "index": 1, "speaker": "Joe", "paragraph": 3} 
] 

for item in data: 
    tags = (
     "index:%d" % item['index'], 
     "speaker:%s" % item['speaker'], 
     "paragraph:%d" % item['paragraph'] 
    ) 
    self.text.insert("end", item['strContent'], tags) 

如果你再进去在“World”中插入“r”,它会继承周围文本的标签

您可以使用返回数据流的dump方法从窗口小部件中获取数据,例如, self.text.dump("1.0", "end-1c", tag=True, text=True, mark=False)产生以下信息:

[ 
('tagon', 'paragraph:3', '1.0'), 
('tagon', 'speaker:Joe', '1.0'), 
('tagon', 'index:0', '1.0'), 
('text', 'Hello', '1.0'), 
('tagoff', 'index:0', '1.5'), 
('tagon', 'index:1', '1.5'), 
('text', 'World', '1.5') 
] 

将数据重新组装为原始格式非常棘手。这是一个粗略的尝试,尽管我不知道它会如何在现实世界中站起来。用户可能会以完全混淆结构的方式编辑数据。

def get_data(self): 
    result = [] 
    meta = {} 
    for item in self.text.dump("1.0", "end-1c", tag=True, text=True, mark=False): 
     if item[0] == "tagon": 
      (name, value) = item[1].split(":") 
      meta[name] = value 

     if item[0] == "tagoff": 
      (name, value) = item[1].split(":") 
      del meta[name] 

     if item[0] == "text": 
      text = item[1] 
      # if this text has the same tags as the previous text, 
      # don't create a new item; instead, append the text to 
      # the previous item 
      if result and all(item in result[-1].items() for item in meta.items()): 
       result[-1]["strContent"] += text 
      else: 
       data = {"strContent": text} 
       data.update(meta) 
       result.append(data) 

    return result 

不知道你实际上试图完成,文本构件可能不是最好的解决方案,因为它为用户提供了一个有点过分自由改变文本。例如,如果他们将“Hello”更改为“HelloWorld”,然后删除原始的“World”,会发生什么?他们最终会得到一个“HelloWorld”项目还是原来的两个“Hello”和“World”项目?

您可能想要考虑使用一个画布,其中每个文本项目都是不同的对象(也可以有标签),或者您可能想要使用一系列的入口小部件,以便一次中的数据可以' t流血到另一个。

+0

谢谢布莱恩。理想情况下,每个单词应该保持自己作为一个独特的对象,文本不应该是可变的。这个词只应该受制于操作:插入(重新定位),删除或复制(和插入)。画布小部件似乎是一个很好的建议,但我担心易于使用以执行上述操作。该用例涉及多页脚本,我想编辑,每个单词保持它的标签。我会尽力实施你所提到的。谢谢你的帮助。 – Acronomic