是否可以在 Tkinter 文本小部件 (python) 中使用自定义对象而不是字符串?
Is it possible to use a custom object instead of String inside a Tkinter Text Widget (python)?
我正在尝试创建一个文本编辑器来处理类似字符串的对象。理想情况下,我想子类化 Tkinter 的文本小部件或其他一些 Gui 模块,以允许我替换此自定义对象而不是使用字符串。
我了解如何创建对象本身(基本上只是用元数据标记每个单词),但不知道如何在保留其其他属性的同时将呈现的对象作为文本进行操作。
例如
文本编辑器导入一个包含 "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 中使这些类似字符串的对象可操作,并可进行剪切、复制、粘贴、删除和重新排列。我不需要让程序允许我输入任何新词或创建新对象,只需操作在转换我打开的文件时已初始化的对象。
如有任何帮助或指导,我们将不胜感激。谢谢
我认为你可以做类似的事情
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
的所有信息
注意:这试图回答所提出的问题,但我怀疑这是一个 xy problem。在这个答案的最后,我会给出一些其他的建议。
文本小部件不能将一些复杂的对象作为其底层数据结构。它可以显示文本,并且可以具有与文本关联的标签。您还可以插入图像和小部件,但我认为这与您的要求无关。
读入数据时,您可以为每个元数据构建标签,并将这些标签与一定范围的文本相关联。例如,单词 "Hello" 可以具有标签 "paragraph:3"、"speaker:Joe" 和 "index: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
方法从小部件中取回数据,其中 returns 数据流。例如,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" 项?
您可能想要考虑使用 canvas,其中每个文本项都是一个不同的对象(也可以有标签),或者您可能想要使用一系列条目小部件,以便一次输入的数据不能渗入另一个。
我正在尝试创建一个文本编辑器来处理类似字符串的对象。理想情况下,我想子类化 Tkinter 的文本小部件或其他一些 Gui 模块,以允许我替换此自定义对象而不是使用字符串。
我了解如何创建对象本身(基本上只是用元数据标记每个单词),但不知道如何在保留其其他属性的同时将呈现的对象作为文本进行操作。
例如
文本编辑器导入一个包含 "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 中使这些类似字符串的对象可操作,并可进行剪切、复制、粘贴、删除和重新排列。我不需要让程序允许我输入任何新词或创建新对象,只需操作在转换我打开的文件时已初始化的对象。
如有任何帮助或指导,我们将不胜感激。谢谢
我认为你可以做类似的事情
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
的所有信息注意:这试图回答所提出的问题,但我怀疑这是一个 xy problem。在这个答案的最后,我会给出一些其他的建议。
文本小部件不能将一些复杂的对象作为其底层数据结构。它可以显示文本,并且可以具有与文本关联的标签。您还可以插入图像和小部件,但我认为这与您的要求无关。
读入数据时,您可以为每个元数据构建标签,并将这些标签与一定范围的文本相关联。例如,单词 "Hello" 可以具有标签 "paragraph:3"、"speaker:Joe" 和 "index: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
方法从小部件中取回数据,其中 returns 数据流。例如,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" 项?
您可能想要考虑使用 canvas,其中每个文本项都是一个不同的对象(也可以有标签),或者您可能想要使用一系列条目小部件,以便一次输入的数据不能渗入另一个。