I have been investigating how to add the capability of using double-click and drag to select a word in a RichTextCtrl and then extend the selection to the right or left while keeping the mouse button pressed. That is standard behaviour in the TextCtrl and StyleTextCtrl, but not in the RichTextCtrl.
Anyhow, I managed to get my scheme to work, but I noticed a strange behaviour relating to drag and drop.
If I double-click on a word, and then wait for a second or so and then click on the word and start dragging the mouse, the cursor changes to indicate a drag operation is happening. However, when I release the mouse button an error dialog appears which says “An error occurred during drag and drop operation”. When you click on the Details button, it says “Could not write the buffer to an XML stream. You may have forgotten to add the XML file handler”.
It seems rather bizarre that it checks for an XML stream after allowing the drag and drop operation, rather than before!
The application I am working on doesn’t need drag and drop, so I wish to prevent it from being triggered. I have found that if I bind EVT_MOTION
and then call self.rtc.SetPreDrag(False)
in the event handler, it does prevent the drag and drop from happening. If the code below is run it shows the default drag and drop behaviour. If you uncomment the self.rtc.Bind()
call in __init__()
, drag and drop should be disabled.
Have I missed a more obvious way to switch off drag and drop?
import wx
import wx.richtext as rt
TEXT = (
"Lorem IPSUM dolor sit amet, consectetur adipiscing elit, "
"sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "
"Vestibulum lectus mauris ultrices eros in cursus turpis. "
"Dui vivamus arcu felis bibendum ut. "
"Ac turpis egestas integer eget aliquet nibh praesent tristique magna. "
"Mauris ultrices eros in cursus turpis massa tincidunt dui. "
"Mi bibendum neque egestas congue. "
"Nunc sed augue lacus viverra vitae congue eu consequat. "
"Consectetur adipiscing elit pellentesque habitant morbi. "
"Pellentesque elit ullamcorper dignissim cras tincidunt lobortis feugiat vivamus at. "
"Ut lectus arcu bibendum at varius. "
"Pellentesque eu tincidunt tortor aliquam nulla facilisi cras fermentum odio. "
"Eget aliquet nibh praesent tristique. "
"Sit amet aliquam id diam maecenas ultricies mi eget. "
"Iaculis nunc sed augue lacus viverra vitae congue eu. "
"Fames ac turpis egestas sed tempus urna. A diam maecenas sed enim ut sem. "
"Aenean pharetra magna ac placerat vestibulum lectus mauris ultrices. "
"Velit egestas dui id ornare arcu odio ut sem nulla. "
"Placerat duis ultricies lacus sed. "
"Libero enim sed faucibus turpis in eu mi bibendum. "
)
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.SetSize((600, 300))
self.SetTitle("Test drag & drop")
self.panel_1 = wx.Panel(self, wx.ID_ANY)
sizer_1 = wx.BoxSizer(wx.VERTICAL)
self.rtc = rt.RichTextCtrl(self.panel_1, wx.ID_ANY)
sizer_1.Add(self.rtc, 1, wx.ALL | wx.EXPAND, 4)
sizer_2 = wx.BoxSizer(wx.HORIZONTAL)
sizer_1.Add(sizer_2, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.BOTTOM | wx.TOP, 8)
self.close_button = wx.Button(self.panel_1, wx.ID_ANY, "Close")
sizer_2.Add(self.close_button, 0, 0, 0)
self.panel_1.SetSizer(sizer_1)
self.Layout()
self.Bind(wx.EVT_BUTTON, self.OnClose, self.close_button)
# UNCOMMENT THE FOLLOWING LINE TO PREVENT DRAG AND DROP
# self.rtc.Bind(wx.EVT_MOTION, self.OnMotion)
self.rtc.SetValue(TEXT)
def OnClose(self, _event):
self.Destroy()
def OnMotion(self, event):
# Prevent drag & drop
self.rtc.SetPreDrag(False)
event.Skip()
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(None, wx.ID_ANY, "")
self.SetTopWindow(self.frame)
self.frame.Show()
return True
if __name__ == "__main__":
app = MyApp(0)
app.MainLoop()
I am using Python 3.8.10 + wxPython 4.1.1 gtk3 (phoenix) wxWidgets 3.1.5 + Linux Mint 20.3