I have been trying to set up styles for URLs in a RichTextCtrl so that they appear as blue, underlined text and when you left-click on them they will trigger an EVT_TEXT_URL event.
That part is working. However, if I click on one of the URLs and then load new text (or even the same text) into the RTC, all the text is marked as URLs!
I have only tested this on wxPython 4.2.3 gtk3 (phoenix) wxWidgets 3.2.7 + Python 3.12.3 + Linux Mint 22.2, so I don’t know if it happens on other platforms.
Below is a simplified example. To trigger the behaviour, left-click on one of the URLs and then click on the “Reload” button.
Any ideas for how to stop this happening?
import re
import wx
import wx.richtext as rt
TEXT = """\
Here are some URLs to test.
Left-click on a URL, then click on "Reload"
and *all* the text will be marked as URLs????
https://wxpython.org/
https://www.bbc.co.uk/news
https://www.theregister.com/Week/
"""
URL_REGEX = re.compile(r'(http|https)://([\w\-_]+(?:\.[\w\-_]+)+)([\w\-.,@?^=%&:/~+#]*[\w\-@?^=%&/~+#])?')
class MyFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent)
self.SetSize(wx.Size(600, 350))
self.SetTitle("Test RichTextCtrl")
self.panel = wx.Panel(self, wx.ID_ANY)
main_sizer = wx.BoxSizer(wx.VERTICAL)
self.rtc = rt.RichTextCtrl(self.panel, wx.ID_ANY)
main_sizer.Add(self.rtc, 1, wx.EXPAND, 0)
bottom_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.reload_button = wx.Button(self.panel, wx.ID_ANY, "Reload")
bottom_sizer.Add(self.reload_button, 0, wx.RIGHT, 16)
self.close_button = wx.Button(self.panel, wx.ID_ANY, "Close")
bottom_sizer.Add(self.close_button, 0, 0, 0)
main_sizer.Add(bottom_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.TOP | wx.BOTTOM, 8)
self.panel.SetSizer(main_sizer)
self.Layout()
self.displayText()
self.rtc.Bind(wx.EVT_TEXT_URL, self.OnURL)
self.reload_button.Bind(wx.EVT_BUTTON, self.OnReload)
self.close_button.Bind(wx.EVT_BUTTON, self.OnClose)
def displayText(self):
print("Display Text:")
self.rtc.SetValue(TEXT)
self.markAllURLs(TEXT)
def markURL(self, start, end, url_text):
"""Mark a URL in the RichTextCtrl. """
url_style = rt.RichTextAttr()
url_style.SetTextColour(wx.BLUE)
url_style.SetFontUnderlined(True)
url_style.SetURL(url_text)
self.rtc.SetStyle(start, end, url_style)
def markAllURLs(self, text):
"""Mark all the URLs in the RichTextCtrl. """
for m in re.finditer(URL_REGEX, text):
print(f" {m.start(0)} {m.end(0)} {m.group(0)}")
self.markURL(m.start(0), m.end(0), m.group(0))
def OnClose(self, _evt):
self.Destroy()
def OnReload(self, _evt):
self.displayText()
def OnURL(self, evt):
print("OnURL()", evt.GetString())
if __name__ == "__main__":
app = wx.App()
frame = MyFrame(None)
frame.Show()
app.MainLoop()