I'm developing an application using wxPython 4.0.4 in Python 3.7.3, and I've run into a problem when trying to color UTF-8 text in a wx.TextCtrl. Basically, it seems that certain characters are counted incorrectly within wxPython despite them being counted correctly in Python.
I initially thought that it was all multi-byte characters were being miss-counted, however, my example code below shows this is not the case. It appears to be a problem specifically in the wx.TextCtrl.SetStyle function.
import wx
import wx.richtext as rt
app = wx.App()
test_str1 = '''There are no multibyte characters '''
test_str2 = '''blah ble blah\n'''
test_str3 = '''“these are multibyte quotes” '''
test_str4 = '''more single byte chars!\n'''
test_str5 = '''this comma’s represented by multiple bytes\n'''
test_str6 = '''why do emojis seem to break TextCtrl.SetStyle \n'''
test_str7 = '''more single byte characters\n'''
test_str8 = '''to demonstrate the issue.'''
def main():
main = TestFrame()
main.Show()
app.MainLoop()
class TestFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="TestFrame")
sizer = wx.BoxSizer(wx.VERTICAL)
self.panel = TestPanel(self)
sizer.Add(self.panel, proportion=1, flag=wx.EXPAND)
class TestPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.text = wx.TextCtrl(self, wx.ID_ANY, style=(wx.TE_MULTILINE|wx.TE_RICH|wx.TE_READONLY))
self.raw_text = ""
self.styles = []
self.AddColorText(test_str1, wx.BLUE)
self.AddColorText(test_str2, wx.RED)
self.AddColorText(test_str3, wx.BLUE)
self.AddColorText(test_str4, wx.RED)
self.AddColorText(test_str5, wx.BLUE)
self.AddColorText(test_str6, wx.RED)
self.AddColorText(test_str7, wx.BLUE)
self.AddColorText(test_str8, wx.RED)
self.text.SetValue(self.raw_text)
for s in self.styles:
self.text.SetStyle(s[0], s[1], s[2])
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.text, proportion=1, flag=wx.EXPAND)
self.SetSizer(sizer)
def AddColorText(self, text, wx_color):
start = len(self.raw_text)
self.raw_text += text
end = len(self.raw_text)
self.styles.append([start, end, wx.TextAttr(wx_color)])
if __name__ == "__main__":
main()