在Tkinter文本小部件(python)中是否可以使用自定义对象而不是字符串?

在Tkinter文本小部件(python)中是否可以使用自定义对象而不是字符串?,python,string,user-interface,tkinter,subclass,Python,String,User Interface,Tkinter,Subclass,我正在尝试创建一个文本编辑器,它将处理一个类似字符串的对象。理想情况下,我希望对Tkinter的文本小部件或其他Gui模块进行子类化,以允许我替换此自定义对象,而不是使用字符串 我了解如何创建对象本身(本质上只是用元数据标记每个单词),但不了解如何在保留其他属性的同时将渲染对象作为文本进行操作 例如 文本编辑器导入一个包含“Hello World”的文件。打开此文本后,这两个单词都带有相关属性的标签。(以下显示为字典,但理想情况下为对象Hello.strContent、Hello.index等)

我正在尝试创建一个文本编辑器,它将处理一个类似字符串的对象。理想情况下,我希望对Tkinter的文本小部件或其他Gui模块进行子类化,以允许我替换此自定义对象,而不是使用字符串

我了解如何创建对象本身(本质上只是用元数据标记每个单词),但不了解如何在保留其他属性的同时将渲染对象作为文本进行操作

例如
文本编辑器导入一个包含“Hello World”的文件。打开此文本后,这两个单词都带有相关属性的标签。(以下显示为字典,但理想情况下为对象Hello.strContent、Hello.index等)

现在我完全搞不懂如何在文本gui中使这些类似字符串的对象可操作,并进行剪切、复制、粘贴、删除和重新排列。我不需要让程序允许我键入任何新词或创建新对象,只要在转换打开的文件时操作已初始化的对象即可


任何帮助或指导都将不胜感激。谢谢。

我想你可以这样做

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将是一个很好的字符串,包含来自hello的所有信息。注意:这试图回答所问的问题,但我怀疑这是一个错误。在这个答案的最后,我将给出一些其他的建议


文本小部件不能有一些复杂的对象作为其底层数据结构。它可以显示文本,并且可以具有与文本关联的标记。您还可以插入图像和小部件,但我认为这与您的要求无关

在中读取数据时,可以为每段元数据构造标记,并将这些标记与一系列文本关联。例如,单词“Hello”可以有标签“段落:3”、“演讲者:Joe”和“索引:0”。“World”与之类似,只是它的标签是“index: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”项目


您可能想考虑使用一个画布,其中每个文本项是一个不同的对象(它也可以有标签),或者您可能想要使用一系列的入口控件,这样数据就不会一次渗入另一个。p> 有没有一个原因可以解释为什么不能将strContent作为字符串添加到文本中,甚至不能引用字典中的每个对象?如中所述,每个单词都是一个字典键,其中分配给该键的值就是您上面概述的字典?我喜欢使用字典的想法,但源文本将包含相同单词的副本。例如,一个丑陋的解决方案会在每个单词的开头添加一个索引来呈现文本。
00和01这里02是03a 04sample 05text 06,07很简单。
现在,假设我在假设的Gui编辑器中编辑此文本,如下所示:
您能创建一个列表吗?在读入对象时,按顺序将每个对象附加到列表中,然后遍历列表并将每个

strContent
添加到
text
widget?现在,假设我在假设的Gui编辑器中编辑此文本以读取:05text 0701此处。现在,我可以使用一个单独的索引列表来交叉引用这些索引值。但是,我希望文本美观易读,因此此解决方案不起作用。如果我创建一个列表并将strContent添加到文本小部件中,如何在文本小部件中重新排列该文本并使其保留每个单词的元数据?我想我想知道文本小部件中的strContent是如何保持与元数据的链接的,因为现在它已经从myObj缩减为str。这确实可以用来显示文本,但我希望在文本显示后对其进行操作,并使每个单词仍然保留其元数据。理想情况下,它可以在文本编辑器(如应用程序)中进行操作,但这会操作MyOBJ而不是字符串。谢谢Bryan。理想情况下,每个单词都应该保持自己作为一个不同的对象,并且文本不应该是可变的。该单词只能执行以下操作:插入(重新定位)、删除或复制(和插入)。canvas小部件似乎是一个很好的建议,但我担心执行上述操作的易用性。这个用例将涉及我想要编辑的多页文本,每一个单词都维护它的标签。我会尽力实现你提到的。谢谢你的帮助。
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