Shu*_*ule 3 python tkinter richtext italics
我有一个 Python Tkinter 程序,我可以在其中选择文本,按快捷键,它将使所选文本变为粗体。您可以对其他样式(例如斜体)使用不同的快捷方式。
\n\n但是,作为正在运行的程序中的用户,我遇到了一个问题,如果我尝试通过快捷方式将已经粗体的文本设置为斜体,那么文本只会显示为斜体,而不是粗体和斜体。我知道这是有道理的,因为标签被分配来执行其中一项操作,并且同时执行两项操作不会合并标签的效果。但是,我不知道如何确定当文本上有多个标签时会发生什么。
\n\n您能否拥有一个以某种方式表示其他两个特定标签重叠的标签?
\n\n我看到处理这个问题的唯一方法(从我在文档中看到的)是使用将Text.tag_bind一个函数绑定到我的每个样式标签,该函数执行一些有趣的操作来制作正确的文本,并且只有正确的文本,无论是粗体还是粗体。斜体。我认为这是可行的,但如果这不是正确的方法,我想知道。
我可以毫不费力地制作一个同时显示粗体和斜体的标签。我需要的是能够处理重叠的标签。
\n\n这是我已经在做的事情的相关代码:
\n\ndef set_tag_styles(self):\n self.myTextWidget.tag_config("bold", font=[self.d["font"][0], self.d["font"][1], "bold"])\n self.myTextWidget.tag_config("italic", font=[self.d["font"][0], self.d["font"][1], "italic"])\n self.myTextWidget.tag_config("underline", font=[self.d["font"][0], self.d["font"][1], "underline"])\n self.myTextWidget.tag_config("overstrike", font=[self.d["font"][0], self.d["font"][1], "overstrike"])\ndef invert_tag(self, start, end=None, tag=SEL, w=None):\n #This just makes text without the tag have the tag and text with the tag not have the tag anymore.\n if w==None:\n w=self.myTextWidget\n i=0\n if end==None:\n if tag in w.tag_names(start):\n w.tag_remove(tag, start)\n else:\n w.tag_add(tag, start)\n else:\n while w.compare(start+"+"+str(i)+"c", "<", end):\n if tag in w.tag_names(start+"+"+str(i)+"c"):\n w.tag_remove(tag, start+"+"+str(i)+"c")\n else:\n w.tag_add(tag, start+"+"+str(i)+"c")\n i+=1\n self.set_tag_styles()\ndef bold_text(self, event=None):\n try:\n self.invert_tag("sel.first", "sel.last", "bold")\n except:\n if self.myTextWidget.get("insert wordstart") in {" ", "\\n", "\\t", "\\r", "\xc2\xa0"}:\n pass\n else:\n self.invert_tag("insert wordstart", "insert wordend", "bold")\n return "break"\ndef italic_text(self, event=None):\n try:\n self.invert_tag("sel.first", "sel.last", "italic")\n except:\n if self.myTextWidget.get("insert wordstart") in {" ", "\\n", "\\t", "\\r", "\xc2\xa0"}:\n pass\n else:\n self.invert_tag("insert wordstart", "insert wordend", "italic")\n return "break"\nRun Code Online (Sandbox Code Playgroud)\n\n编辑:对于那些感兴趣的人(并且不想从头开始编写所有代码),这里是我为使其工作而所做的代码(使用 Bryan Oakley 的答案作为指导):
\n\nself.style_tags={"bold", "italic", "underline", "overstrike", "bold italic", "bold italic underline", "bold italic underline overstrike", "italic underline", "italic overstrike", "italic underline overstrike", "underline overstrike", "bold underline", "bold underline overstrike", "bold overstrike", "bold italic overstrike"};\n \xe2\x80\xa6\n def clear_multiple_styles(self, pos, w=None):\n #This gets rid of all multi-style tags (like "bold italic underline").\n if w==None:\n w=self.myTextWidget;\n for x in self.style_tags:\n s=Switch(); #This is my version of a switch statement (so I don\'t have to type my compare variable every time), with added flexibility.\n s.switch(x);\n if s.neq("bold", "italic", "underline", "overstrike"): #This means, if x isn\'t equal to any of them\n if x in w.tag_names(pos):\n w.tag_remove(x, pos);\n def update_style(self, pos, w=None):\n #This updates the styles of an index to take care of overlapping style tags.\n if w==None:\n w=self.myTextWidget;\n self.clear_multiple_styles(pos, w);\n s=Switch();\n s.switch(w.tag_names(pos));\n if s.ins("bold", "italic", "underline", "overstrike"): #i.e. If these args are all in w.tag_names(pos)\n w.tag_add("bold italic underline overstrike", pos);\n elif s.ins("bold", "italic", "underline"):\n w.tag_add("bold italic underline", pos);\n elif s.ins("bold", "italic", "overstrike"):\n w.tag_add("bold italic overstrike", pos);\n elif s.ins("bold", "italic"):\n w.tag_add("bold italic", pos);\n elif s.ins("bold", "underline", "overstrike"):\n w.tag_add("bold underline overstrike", pos);\n elif s.ins("bold", "underline"):\n w.tag_add("bold underline", pos);\n elif s.ins("bold", "overstrike"):\n w.tag_add("bold overstrike", pos);\n elif s.ins("italic", "underline", "overstrike"):\n w.tag_add("italic underline overstrike", pos);\n elif s.ins("italic", "underline"):\n w.tag_add("italic underline", pos);\n elif s.ins("italic", "overstrike"):\n w.tag_add("italic overstrike", pos);\n elif s.ins("underline", "overstrike"):\n w.tag_add("underline overstrike", pos);\n def invert_style_tag(self, start, end=None, tag="bold", w=None):\n if w==None:\n w=self.myTextWidget;\n i=0;\n if end==None:\n if tag in w.tag_names(start):\n w.tag_remove(tag, start);\n else:\n w.tag_add(tag, start);\n self.update_style(start);\n else:\n while w.compare(start+"+"+str(i)+"c", "<", end):\n if tag in w.tag_names(start+"+"+str(i)+"c"):\n w.tag_remove(tag, start+"+"+str(i)+"c");\n else:\n w.tag_add(tag, start+"+"+str(i)+"c");\n self.update_style(start+"+"+str(i)+"c");\n i+=1;\n self.set_tag_styles();\n def set_tag_styles(self):\n single_styles={"bold", "italic", "underline", "overstrike"};\n for x in self.style_tags:\n x_list=x.split();\n self.myTextWidget.tag_config(x, font=[self.d["font"][0], self.d["font"][1]]+x_list); #You can add lists together to get the extra arguments in.\n for y in single_styles:\n if x not in single_styles:\n self.myTextWidget.tag_raise(x); #Gives the multi-style tag higher priority than existing single-style tags\n def style_text(self, style):\n try:\n self.invert_style_tag("sel.first", "sel.last", style);\n except:\n if self.myTextWidget.get("insert wordstart") in {" ", "\\n", "\\t", "\\r", "\xc2\xa0"}:\n pass;\n else:\n self.invert_style_tag("insert wordstart", "insert wordend", style);\n def bold_text(self, event=None):\n self.style_text("bold");\n return "break";\n def italic_text(self, event=None):\n self.style_text("italic");\n return "break";\n def underline_text(self, event=None):\n self.style_text("underline");\n return "break";\n def overstrike_text(self, event=None):\n self.style_text("overstrike");\n return "break";\nRun Code Online (Sandbox Code Playgroud)\n\n对于那些想要我的 Switch 类代码(而不是将其转换为标准表达式)的人,这里是(如果这对您来说代码太多,请提前抱歉):
\n\nclass Switch:\n def switch(self, item):\n self.item=item;\n def case(self, values, operator="=="):\n #values must be a list, set, tuple or other sequence. This is to allow one not to have to define operator. If you don\'t like this, use the other methods.\n if operator in "==":\n return self.eq(*values);\n elif operator=="!" or operator=="!=":\n return self.neq(*values);\n elif operator==">":\n return self.gr(*values);\n elif operator=="<":\n return self.ls(*values);\n elif operator==">=":\n return self.gre(*values);\n elif operator=="<=":\n return self.lse(*values);\n elif operator in "range" and operator[0]=="r":\n if len(values)!=2:\n raise ValueError("There must be two and only two values in a range.");\n return self.range(values[0], values[1]);\n elif operator in "nrange" and operator[0]=="n":\n if len(values)!=2:\n raise ValueError("There must be two and only two values in an nrange.");\n return self.nrange(values[0], values[1]);\n else:\n raise ValueError("The operator "+operator+" is not currently defined.");\n def ins(self, *values):\n #If all the values are part of the string or sequence, self.item, return True. Else return False.\n #Note: It doesn\'t take into account that "" is in every string and some tuples.\n for x in values:\n if x not in self.item:\n return False;\n return True;\n def eq(self, *values):\n #Equal to\n return self.item in values;\n def gr(self, *values):\n #Greater than\n for x in values:\n if self.item<=x:\n return False;\n return True;\n def gre(self, *values):\n #Greater than or equal to\n for x in values:\n if self.item<x:\n return False;\n return True;\n def ls(self, *values):\n #Less than\n for x in values:\n if self.item>=x:\n return False;\n return True;\n def lse(self, *values):\n #Less than or equal to\n for x in values:\n if self.item>x:\n return False;\n return True;\n def neq(self, *values):\n return self.item not in values;\n def range(self, min, max):\n return self.item in range(min, max) or max==self.item or min==self.item;\n def nrange(self, min, max):\n return self.item not in range(min, max) and max!=self.item and min!=self.item;\nRun Code Online (Sandbox Code Playgroud)\n
问题不在于重叠标签本身,而在于您尝试使用重叠字体。如果两个标签定义了字体属性,则仅使用具有较高优先级的标签的字体。
唯一的选择是为“bold-italic”创建第三个标记,并定义适当的字体。然后,当您想要将某些内容加粗或斜体时,您需要有一个特殊的情况来处理适当使用第三个标签(即:如果范围没有标签,则添加斜体,如果有粗体,请将其更改为粗体-斜体等)。