Python 在文本小部件中应用标记
我需要一些帮助标签相关 我正在编写一个简单的编辑器,支持基本格式。 通过使用一个文本小部件(名为Text),我放置了一个标记“b”,以设置该标记应用于粗体的文本 当我将粗体应用于选择时,这不是问题:Python 在文本小部件中应用标记,python,tkinter,Python,Tkinter,我需要一些帮助标签相关 我正在编写一个简单的编辑器,支持基本格式。 通过使用一个文本小部件(名为Text),我放置了一个标记“b”,以设置该标记应用于粗体的文本 当我将粗体应用于选择时,这不是问题: text.tag_add('b', SEL_FIRST,SEL_LAST) 当我只想在打字时打开/关闭粗体时,我遇到了两个问题。 要打开它,我找到的唯一方法是: text.insert(INSERT, ' ', 'b' ) text.mark_set("insert", INSERT+'-1c'
text.tag_add('b', SEL_FIRST,SEL_LAST)
当我只想在打字时打开/关闭粗体时,我遇到了两个问题。
要打开它,我找到的唯一方法是:
text.insert(INSERT, ' ', 'b' )
text.mark_set("insert", INSERT+'-1c')
请注意,我必须插入两个空格。如果我插入一个,则粗体不适用。如果插入“”,则光标返回一个字符
我的第二个问题是,当我在一个粗体区域内写作时,如何关闭它——对此我一点也不知道
谢谢你的帮助 你可能没有意识到这一点,但你正试图做一些在Tkinter非常困难的事情。虽然文本小部件标签是一个强大的概念,但在创建wysywig编辑器之类的东西时,它们有一些弱点 你需要改变一下你的方法。我认为更好的解决方案不是插入空格,而是在每次插入字符时添加应用(或删除)标记的绑定。这有它自己的一套问题,但只要对细节有足够的关注,你就能克服它们。我们可以通过自定义密钥绑定来实现这一点 将字符插入文本小部件时,这由文本小部件类上的
事件上的绑定处理。因此,我们可以绑定到
来添加标记。但是,如果我们向小部件上的
添加绑定,这将在类绑定之前触发,这意味着我们的代码将在插入字符之前而不是之后执行。我们将尝试修改一些尚未实际插入小部件的内容
解决这个问题的一种方法是绑定到按键释放,而不是按键,因为字符是插入到按键上的。然而,想象一下这样一个场景:用户按下并按住一个键——将输入多个字符,但您可能只得到一个向上键事件。所以这个解决方案不是特别好
另一个解决方案是以某种方式安排自定义绑定在默认绑定之后进行。要做到这一点,我们需要做两件事:1)调整小部件的“绑定标记”,使其在类标记之后有一个额外的标记,以及2)向这个新的绑定标记添加一个绑定
这种方法也有缺点。不是因为绑定标签,而是因为除了
(例如,要粘贴的control-v不是由
绑定处理的,因此您必须为粘贴添加一个特殊情况)之外,还需要处理更多的事件
这就是说,这个解决方案可能对您来说已经足够好了,或者至少可以帮助您更好地理解问题,而理解问题往往是找到解决方案的最大障碍
在下面的示例中,我有一个文本小部件,它有一个名为“CustomText”的附加bindtag,我们将它放在标准的“text”绑定标记之后。我为
事件在这个标记上添加了一个绑定,在处理程序中,我只需将适当的标记应用于刚刚插入的字符
您必须添加自己的代码来处理剪贴板粘贴,以及处理冲突标记的问题(例如两个标记各有自己的字体)。不过,希望这个例子能起到启发作用
import Tkinter as tk
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.tag_vars = {
"underline": tk.IntVar(),
"red": tk.IntVar(),
}
self.text = MyText(self, width=40, height=8)
self.text.tag_configure("red", foreground="red")
self.text.tag_configure("underline", underline=True)
toolbar = tk.Frame(self)
self.underline = tk.Checkbutton(self, text="Underline",
onvalue = True, offvalue=False,
variable = self.tag_vars["underline"]
)
self.red = tk.Checkbutton(self, text="Red",
onvalue = True, offvalue=False,
variable = self.tag_vars["red"]
)
self.underline.pack(in_=toolbar, side="left")
self.red.pack(in_=toolbar, side="left")
toolbar.pack(side="top", fill="x")
self.text.pack(side="top", fill="both", expand=True)
class MyText(tk.Text):
def __init__(self, parent, *args, **kwargs):
tk.Text.__init__(self, *args, **kwargs)
self.parent = parent
# add a new bind tag, "CustomText" so we
# can have code run after the class binding
# has done it's work
bindtags = list(self.bindtags())
i = bindtags.index("Text")
bindtags.insert(i+1, "CustomText")
self.bindtags(tuple(bindtags))
# set a binding that will fire whenever a
# self-inserting key is pressed
self.bind_class("CustomText", "<Key>", self.OnKey)
def OnKey(self, event):
# we are assuming this is called whenever
# a character is inserted. Apply or remove
# each tag depending on the state of the checkbutton
for tag in self.parent.tag_vars.keys():
use_tag = self.parent.tag_vars[tag].get()
if use_tag:
self.tag_add(tag, "insert-1c", "insert")
else:
self.tag_remove(tag, "insert-1c", "insert")
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
将Tkinter作为tk导入
类SampleApp(tk.tk):
定义初始化(self,*args,**kwargs):
tk.tk.\uuuuu初始化(self,*args,**kwargs)
self.tag_vars={
“下划线”:tk.IntVar(),
“红色”:tk.IntVar(),
}
self.text=MyText(self,宽度=40,高度=8)
self.text.tag\u configure(“红色”,前台=“红色”)
self.text.tag_configure(“underline”,underline=True)
工具栏=tk.Frame(self)
self.underline=tk.Checkbutton(self,text=“underline”,
onvalue=True,offvalue=False,
变量=self.tag_vars[“下划线”]
)
self.red=tk.Checkbutton(self,text=“red”,
onvalue=True,offvalue=False,
变量=self.tag_vars[“红色”]
)
self.underline.pack(在工具栏中,side=“left”)
self.red.pack(在工具栏中,side=“left”)
工具栏包装(side=“top”,fill=“x”)
self.text.pack(side=“top”,fill=“both”,expand=True)
类MyText(tk.Text):
定义初始化(自、父、*args、**kwargs):
tk.Text.\uuuu init\uuuuu(self,*args,**kwargs)
self.parent=parent
#添加一个新的绑定标记“CustomText”,以便
#可以在类绑定后运行代码
#已经完成了它的工作
bindtags=list(self.bindtags())
i=bindtags.index(“文本”)
bindtags.insert(i+1,“自定义文本”)
self.bindtags(元组(bindtags))
#设置一个绑定,该绑定将在
#按下自动插入键
self.bind_类(“CustomText”,“self.OnKey”)
def OnKey(自我,事件):
#我们假设它在任何时候都被调用
#插入一个字符。应用或删除
#每个标签取决于checkbutton的状态
对于self.parent.tag_vars.keys()中的标记:
使用\u tag=self.parent.tag\u vars[tag].get()
如果使用_标签:
自我标记添加(标记“插入-1c”、“插入”)
其他:
自行拆除标签(标签“插入-1c”、“插入”)
如果名称=“\uuuuu main\uuuuuuuu”:
app=SampleApp()
app.mainloop()
谢谢你,Bryan,但是在我看来,你的方法太复杂了,我也不太想开始为缺少的东西编写绑定—例如粘贴
我简单地写下了以下内容,它似乎起了作用
l=text.tag_names('insert')
if l==() or l[0]!='b': # select bold
text.insert(INSERT, ' ', 'b' )
text.mark_set('insert', 'insert-1c')
else: # deselect bold
text.insert(INSERT, ' ' )
text.tag_remove ('b','insert-1c')
text.mark_set('insert', 'insert-1c')
我唯一剩下的问题是,在选择粗体时,我还没有找到不插入额外空格的方法,但我可以接受它