python - Tkinter: italicizing already bold text (overlapping tags) -


i have python tkinter program can select text, press shortcut , make selected text bold. can use different shortcuts other styles such italics.

however, i'm having problem while user in running program if try make bold text italicized via shortcut, text appears italicized , not both bold , italics. know makes sense, because tags assigned 1 or other, , doing both isn't going merge effect of tags. however, don't know of way determine happens when have multiple tags on text.

can have tag somehow represents overlap of 2 other specific tags?

the way see handle (from see in documentation) use text.tag_bind bind function each of style tags interesting stuff make proper text, , proper text, both bold , italic. suppose that's doable, if it's not right way it, i'd know.

i don't have trouble making tag both bold , italics @ once. need able handle overlapped tags.

here's pertinent code of i'm doing already:

def set_tag_styles(self):     self.mytextwidget.tag_config("bold", font=[self.d["font"][0], self.d["font"][1], "bold"])     self.mytextwidget.tag_config("italic", font=[self.d["font"][0], self.d["font"][1], "italic"])     self.mytextwidget.tag_config("underline", font=[self.d["font"][0], self.d["font"][1], "underline"])     self.mytextwidget.tag_config("overstrike", font=[self.d["font"][0], self.d["font"][1], "overstrike"]) def invert_tag(self, start, end=none, tag=sel, w=none):     #this makes text without tag have tag , text tag not have tag anymore.     if w==none:         w=self.mytextwidget     i=0     if end==none:         if tag in w.tag_names(start):             w.tag_remove(tag, start)         else:             w.tag_add(tag, start)     else:         while w.compare(start+"+"+str(i)+"c", "<", end):             if tag in w.tag_names(start+"+"+str(i)+"c"):                 w.tag_remove(tag, start+"+"+str(i)+"c")             else:                 w.tag_add(tag, start+"+"+str(i)+"c")             i+=1     self.set_tag_styles() def bold_text(self, event=none):     try:         self.invert_tag("sel.first", "sel.last", "bold")     except:         if self.mytextwidget.get("insert wordstart") in {" ", "\n", "\t", "\r", " "}:             pass         else:             self.invert_tag("insert wordstart", "insert wordend", "bold")     return "break" def italic_text(self, event=none):     try:         self.invert_tag("sel.first", "sel.last", "italic")     except:         if self.mytextwidget.get("insert wordstart") in {" ", "\n", "\t", "\r", " "}:             pass         else:             self.invert_tag("insert wordstart", "insert wordend", "italic")     return "break" 

edit: interested (and not wanting code scratch), here's code of did work (using bryan oakley's answer guidance):

self.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"};     …     def clear_multiple_styles(self, pos, w=none):         #this gets rid of multi-style tags (like "bold italic underline").         if w==none:             w=self.mytextwidget;         x in self.style_tags:             s=switch(); #this version of switch statement (so don't have type compare variable every time), added flexibility.             s.switch(x);             if s.neq("bold", "italic", "underline", "overstrike"): #this means, if x isn't equal of them                 if x in w.tag_names(pos):                     w.tag_remove(x, pos);     def update_style(self, pos, w=none):         #this updates styles of index take care of overlapping style tags.         if w==none:             w=self.mytextwidget;         self.clear_multiple_styles(pos, w);         s=switch();         s.switch(w.tag_names(pos));         if s.ins("bold", "italic", "underline", "overstrike"): #i.e. if these args in w.tag_names(pos)             w.tag_add("bold italic underline overstrike", pos);         elif s.ins("bold", "italic", "underline"):             w.tag_add("bold italic underline", pos);         elif s.ins("bold", "italic", "overstrike"):             w.tag_add("bold italic overstrike", pos);         elif s.ins("bold", "italic"):             w.tag_add("bold italic", pos);         elif s.ins("bold", "underline", "overstrike"):             w.tag_add("bold underline overstrike", pos);         elif s.ins("bold", "underline"):             w.tag_add("bold underline", pos);         elif s.ins("bold", "overstrike"):             w.tag_add("bold overstrike", pos);         elif s.ins("italic", "underline", "overstrike"):             w.tag_add("italic underline overstrike", pos);         elif s.ins("italic", "underline"):             w.tag_add("italic underline", pos);         elif s.ins("italic", "overstrike"):             w.tag_add("italic overstrike", pos);         elif s.ins("underline", "overstrike"):             w.tag_add("underline overstrike", pos);     def invert_style_tag(self, start, end=none, tag="bold", w=none):         if w==none:             w=self.mytextwidget;         i=0;         if end==none:             if tag in w.tag_names(start):                 w.tag_remove(tag, start);             else:                 w.tag_add(tag, start);             self.update_style(start);         else:             while w.compare(start+"+"+str(i)+"c", "<", end):                 if tag in w.tag_names(start+"+"+str(i)+"c"):                     w.tag_remove(tag, start+"+"+str(i)+"c");                 else:                     w.tag_add(tag, start+"+"+str(i)+"c");                 self.update_style(start+"+"+str(i)+"c");                 i+=1;         self.set_tag_styles();     def set_tag_styles(self):         single_styles={"bold", "italic", "underline", "overstrike"};         x in self.style_tags:             x_list=x.split();             self.mytextwidget.tag_config(x, font=[self.d["font"][0], self.d["font"][1]]+x_list); #you can add lists arguments in.             y in single_styles:                 if x not in single_styles:                     self.mytextwidget.tag_raise(x); #gives multi-style tag higher priority existing single-style tags     def style_text(self, style):         try:             self.invert_style_tag("sel.first", "sel.last", style);         except:             if self.mytextwidget.get("insert wordstart") in {" ", "\n", "\t", "\r", " "}:                 pass;             else:                 self.invert_style_tag("insert wordstart", "insert wordend", style);     def bold_text(self, event=none):         self.style_text("bold");         return "break";     def italic_text(self, event=none):         self.style_text("italic");         return "break";     def underline_text(self, event=none):         self.style_text("underline");         return "break";     def overstrike_text(self, event=none):         self.style_text("overstrike");         return "break"; 

for want switch class code (instead of translating standard expressions), here (sorry in advance if code you):

class switch:     def switch(self, item):         self.item=item;     def case(self, values, operator="=="):         #values must list, set, tuple or other sequence. allow 1 not have define operator. if don't this, use other methods.         if operator in "==":             return self.eq(*values);         elif operator=="!" or operator=="!=":             return self.neq(*values);         elif operator==">":             return self.gr(*values);         elif operator=="<":             return self.ls(*values);         elif operator==">=":             return self.gre(*values);         elif operator=="<=":             return self.lse(*values);         elif operator in "range" , operator[0]=="r":             if len(values)!=2:                 raise valueerror("there must 2 , 2 values in range.");             return self.range(values[0], values[1]);         elif operator in "nrange" , operator[0]=="n":             if len(values)!=2:                 raise valueerror("there must 2 , 2 values in nrange.");             return self.nrange(values[0], values[1]);         else:             raise valueerror("the operator "+operator+" not defined.");     def ins(self, *values):         #if values part of string or sequence, self.item, return true. else return false.         #note: doesn't take account "" in every string , tuples.         x in values:             if x not in self.item:                 return false;         return true;     def eq(self, *values):         #equal         return self.item in values;     def gr(self, *values):         #greater         x in values:             if self.item<=x:                 return false;         return true;     def gre(self, *values):         #greater or equal         x in values:             if self.item<x:                 return false;         return true;     def ls(self, *values):         #less         x in values:             if self.item>=x:                 return false;         return true;     def lse(self, *values):         #less or equal         x in values:             if self.item>x:                 return false;         return true;     def neq(self, *values):         return self.item not in values;     def range(self, min, max):         return self.item in range(min, max) or max==self.item or min==self.item;     def nrange(self, min, max):         return self.item not in range(min, max) , max!=self.item , min!=self.item; 

the problem isn't overlapping tags per se, it's you're trying use overlapping fonts. if 2 tags define font property, font tag higher priority used.

the option create third tag "bold-italic" has appropriate font defined. then, when want bold or italicize something, you'll need have special case handle use third tag appropriately (ie: if range has no tags, add italic, if has bold, change bold-italic, etc).


Comments

Popular posts from this blog

google api - Incomplete response from Gmail API threads.list -

Installing Android SQLite Asset Helper -

Qt Creator - Searching files with Locator including folder -