Unexpected characters appended to text strings when using wx.TextDropTarget

I am using wx.TextDropTarget to implement a drag and drop app where users can drag some text strings from a ListCtrl widget and drop them into TextCtrl widgets. One problem that I haven’t been able to figure out how to solve is that sometimes text strings dropped in TextCtrl widgets have random characters appended to the end (see screenshot below). This problem does not arise every single time – as you can see, “East of Eden” is displayed fine

I am on OSX 10.10.5 and using wxPython 2.9.2.4-1. I am not sure if this problem can be reproduced on other platforms. A sample code is below.

import wx

from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin

class AutoWidthListCtrl(wx.ListCtrl, ListCtrlAutoWidthMixin):
def init(self, parent):
wx.ListCtrl.init(self, parent, -1, style=wx.LC_REPORT)
ListCtrlAutoWidthMixin.init(self)

class TextDropTarget(wx.TextDropTarget):
def init(self, obj):
wx.TextDropTarget.init(self)
self.obj = obj

def OnDropText(self, x, y, text):
    self.obj.WriteText(text)

def OnDragOver(self, x, y, d):
    return wx.DragCopy

class MyApp(wx.Frame):
def init(self, parent, title):
super(MyApp, self).init(parent, style = wx.DEFAULT_FRAME_STYLE,
title=title, size=(500, 500))
self.Panel = wx.Panel(self, size = (-1, -1))
GridBagSizer = wx.GridBagSizer(5,5)

    #ListCtrl widget
    self.Source = AutoWidthListCtrl(self.Panel)
    self.Source.Show()
    self.Source.InsertColumn(0, 'Book Titles')
    self.Source.InsertStringItem(0,'War and Peace')
    self.Source.InsertStringItem(0,'East of Eden')
    self.Source.InsertStringItem(0,'Pride and Prejudice')

    GridBagSizer.Add(self.Source, pos = (0, 0), span = (6, 1),
                     flag = wx.EXPAND|wx.ALL, border = 15)
    self.Panel.SetSizer(GridBagSizer)

    #Label for each TextCtrl widget
    AmericanNovel = wx.StaticText(self.Panel, label ="American Novel:")
    EnglishNovel = wx.StaticText(self.Panel, label = "British Novel:")
    RussianNovel = wx.StaticText(self.Panel, label = "Russian Novel:")      
    GridBagSizer.Add(AmericanNovel, pos = (0, 1), span = (1, 1),
                     flag = wx.TOP, border = 10)
    GridBagSizer.Add(EnglishNovel, pos = (2, 1), span = (1, 1))
    GridBagSizer.Add(RussianNovel, pos = (4, 1), span = (1, 1))                      

    #TextCtrl widgets        
    self.Target1 = wx.TextCtrl(self.Panel, size = (240, -1),
                               style = wx.TE_READONLY)
    self.Target2 = wx.TextCtrl(self.Panel, size = (240, -1),
                               style = wx.TE_READONLY)
    self.Target3 = wx.TextCtrl(self.Panel, size = (240, -1),
                               style = wx.TE_READONLY)

    GridBagSizer.Add(self.Target1, pos = (1, 1), span = (1, 1))
    GridBagSizer.Add(self.Target2, pos = (3, 1), span = (1, 1))
    GridBagSizer.Add(self.Target3, pos = (5, 1), span = (1, 1))                      

    dt1 = TextDropTarget(self.Target1)
    dt2 = TextDropTarget(self.Target2)
    dt3 = TextDropTarget(self.Target3)
    self.Target1.SetDropTarget(dt1)
    self.Target2.SetDropTarget(dt2)
    self.Target3.SetDropTarget(dt3)

    self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.OnDragInit)

    GridBagSizer.AddGrowableCol(0)
    GridBagSizer.AddGrowableCol(1)        

def OnDragInit(self, evt):
    text = self.Source.GetItemText(evt.GetIndex())
    tdo = wx.TextDataObject(text)
    tds = wx.DropSource(self.Source)
    tds.SetData(tdo)
    tds.DoDragDrop(True)

if name == “main”:
app = wx.App()
MainFrame = MyApp(None, title = “My App”)
MainFrame.Show()
MainFrame.Centre()
app.MainLoop()

``

Any pointer would be appreciated!

First validate "text", "tdo", "tds" types in OnDragInit() with just
print(type(text)) to be sure they are the expected types. Although it looks
right to me it seems perhaps you are getting a "list item" object instead
of the text string of the list item.

Hello there. I just started my adventure with wxPython and I have encountered exactly the same issue.
In app I’m trying to build you have many TextCtrl components and you should be able to copy text from one to another (using Right Mouse Button).

It’s almost working, but I’m getting some extra characters while doing so.

I’m on OSX 10.13.3, using wxPython 4.0.1 and Python 2.7.10

Here’s my code:

import wx
import wx.xrc

class TextDropTarget(wx.TextDropTarget):
    def __init__(self, obj):
        wx.TextDropTarget.__init__(self)
        self.obj = obj

    def OnDropText(self, x, y, data):
        print "OnDropText"
        print data
        print type(data)
        self.obj.WriteText(data)
        return True

class MainFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=wx.EmptyString, pos=wx.DefaultPosition, size=wx.Size(500, 300), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)

        self.SetSizeHints(wx.DefaultSize, wx.DefaultSize)

        b_sizer = wx.BoxSizer(wx.VERTICAL)

        for x in range(10):
            textCtrl = wx.TextCtrl( self,
                                    wx.ID_ANY, wx.EmptyString,
                                    wx.DefaultPosition,
                                    wx.Size(-1, 40),
                                    wx.TE_MULTILINE
                        )

            b_sizer.Add(textCtrl, 0, wx.ALL | wx.EXPAND, 5)

            dt1 = TextDropTarget(textCtrl)
            textCtrl.SetDropTarget(dt1)

            textCtrl.Bind(wx.EVT_RIGHT_DOWN, self.OnDragInit)

        self.SetSizer(b_sizer)
        self.Centre(wx.BOTH)

    def OnDragInit(self, event):
        tf = event.GetEventObject()
        str = tf.GetValue()
        print str
        print type(str)

        # Create a Text Data Object, which holds the text that is to be dragged
        tdo = wx.TextDataObject(str)

        # Create a Drop Source Object, which enables the Drag operation
        tds = wx.DropSource(tf)

        # Associate the Data to be dragged with the Drop Source Object
        tds.SetData(tdo)

        # Initiate the Drag Operation
        tds.DoDragDrop(True)

if __name__ == '__main__':
    app = wx.App(False)
    frame = MainFrame(None).Show()
    app.MainLoop()

``

Did I missed something obvious in here? Or there’s some kind of bug?

The string seems fine in OnDragInit function, but when I’m printing data in OnDropText it already has the extra characters.

Just to be sure it’s not something extra from the TextCtrl I even used hardcoded text for TextDataObject and still no luck.

What I also find weird it’s very inconsistent. Sometimes it doesn’t happen at all, then after restarting the app it does happen every single time. Also sometimes data in OnDropText function comes completely empty.

And one more thing I’m curious about is the TextDataObject.

I did something like:

tdo = wx.TextDataObject('123')
print tdo.GetText()
print tdo.GetTextLength()

``

and what is my console showing?

123

4

Shouldn’t text length be 3 in this case?

Is anyone else struggling with such a things?

Best Regards,

3vilguy

Alex,

Your code appears to run correctly under Windows 7, Python 3.5.2 and wxPython 4.0.1 msw (phoenix).

With the latest version of wxPython, function these deprecation warnings were reported:

34: wxPyDeprecationWarning: Call to deprecated item. Use InsertItem instead.

self.Source.InsertStringItem(0,‘War and Peace’)

35: wxPyDeprecationWarning: Call to deprecated item. Use InsertItem instead.

self.Source.InsertStringItem(0,‘East of Eden’)

36: wxPyDeprecationWarning: Call to deprecated item. Use InsertItem instead.

self.Source.InsertStringItem(0,‘Pride and Prejudice’)

I made the suggested changes to use InsertItem().

Your code results in another warning:

TypeError: invalid result from TextDropTarget.OnDropText(), a ‘bool’ is expected not ‘NoneType’

but it still appears to run correctly.

This doesn’t answer your original question, but does indicate that the code works on at least one combination of OS, Python and wxPython versions.

···

On Thursday, March 24, 2016 at 9:02:55 PM UTC-6, Alex wrote:

I am using wx.TextDropTarget to implement a drag and drop app where users can drag some text strings from a ListCtrl widget and drop them into TextCtrl widgets. One problem that I haven’t been able to figure out how to solve is that sometimes text strings dropped in TextCtrl widgets have random characters appended to the end (see screenshot below). This problem does not arise every single time – as you can see, “East of Eden” is displayed fine

I am on OSX 10.10.5 and using wxPython 2.9.2.4-1. I am not sure if this problem can be reproduced on other platforms. A sample code is below.

import wx

from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin

class AutoWidthListCtrl(wx.ListCtrl, ListCtrlAutoWidthMixin):
def init(self, parent):
wx.ListCtrl.init(self, parent, -1, style=wx.LC_REPORT)
ListCtrlAutoWidthMixin.init(self)

class TextDropTarget(wx.TextDropTarget):
def init(self, obj):
wx.TextDropTarget.init(self)
self.obj = obj

def OnDropText(self, x, y, text):
    self.obj.WriteText(text)

def OnDragOver(self, x, y, d):
    return wx.DragCopy

class MyApp(wx.Frame):
def init(self, parent, title):
super(MyApp, self).init(parent, style = wx.DEFAULT_FRAME_STYLE,
title=title, size=(500, 500))
self.Panel = wx.Panel(self, size = (-1, -1))
GridBagSizer = wx.GridBagSizer(5,5)

    #ListCtrl widget
    self.Source = AutoWidthListCtrl(self.Panel)
    self.Source.Show()
    self.Source.InsertColumn(0, 'Book Titles')
    self.Source.InsertStringItem(0,'War and Peace')
    self.Source.InsertStringItem(0,'East of Eden')
    self.Source.InsertStringItem(0,'Pride and Prejudice')

    GridBagSizer.Add(self.Source, pos = (0, 0), span = (6, 1),
                     flag = wx.EXPAND|wx.ALL, border = 15)
    self.Panel.SetSizer(GridBagSizer)

    #Label for each TextCtrl widget
    AmericanNovel = wx.StaticText(self.Panel, label ="American Novel:")
    EnglishNovel = wx.StaticText(self.Panel, label = "British Novel:")
    RussianNovel = wx.StaticText(self.Panel, label = "Russian Novel:")      
    GridBagSizer.Add(AmericanNovel, pos = (0, 1), span = (1, 1),
                     flag = wx.TOP, border = 10)
    GridBagSizer.Add(EnglishNovel, pos = (2, 1), span = (1, 1))
    GridBagSizer.Add(RussianNovel, pos = (4, 1), span = (1, 1))                      

    #TextCtrl widgets        
    self.Target1 = wx.TextCtrl(self.Panel, size = (240, -1),
                               style = wx.TE_READONLY)
    self.Target2 = wx.TextCtrl(self.Panel, size = (240, -1),
                               style = wx.TE_READONLY)
    self.Target3 = wx.TextCtrl(self.Panel, size = (240, -1),
                               style = wx.TE_READONLY)

    GridBagSizer.Add(self.Target1, pos = (1, 1), span = (1, 1))
    GridBagSizer.Add(self.Target2, pos = (3, 1), span = (1, 1))
    GridBagSizer.Add(self.Target3, pos = (5, 1), span = (1, 1))                      

    dt1 = TextDropTarget(self.Target1)
    dt2 = TextDropTarget(self.Target2)
    dt3 = TextDropTarget(self.Target3)
    self.Target1.SetDropTarget(dt1)
    self.Target2.SetDropTarget(dt2)
    self.Target3.SetDropTarget(dt3)

    self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.OnDragInit)

    GridBagSizer.AddGrowableCol(0)
    GridBagSizer.AddGrowableCol(1)        


def OnDragInit(self, evt):
    text = self.Source.GetItemText(evt.GetIndex())
    tdo = wx.TextDataObject(text)
    tds = wx.DropSource(self.Source)
    tds.SetData(tdo)
    tds.DoDragDrop(True)

if name == “main”:
app = wx.App()
MainFrame = MyApp(None, title = “My App”)
MainFrame.Show()
MainFrame.Centre()
app.MainLoop()

``

Any pointer would be appreciated!

Did you read the documentation?

···

3vilguy wrote:

      And one more thing I'm curious about is the

TextDataObject.

I did something like:

tdo = wx.TextDataObject('123')
print tdo.GetText()
print tdo.GetTextLength()

``

and what is my console showing?

123

4

Shouldn’t text length be 3 in this case?

    By default,

returns the size of the text data set in the constructor or
using SetText . This can be overridden
to provide text size data on-demand. It is recommended to return
the text length plus 1 for a trailing zero, but this is not
strictly required.

-- Tim Roberts, Providenza & Boekelheide, Inc.

timr@probo.com

Thanks Tim.

Yes, I saw the documentation, but to be fair “It is recommended to return” is not the same as “By default it returns…”
If that’s the case then length 4 is nothing to be worried about, but the main problem (unexpected characters appended to text string) is still there.

Best Regards,

3vilguy