uhz
uhz

Reputation: 2528

wxpython drag&drop focus problem

I'd like to implement drag&drop in wxPython that works in similar way that in WordPad/Eclipse etc. I mean the following:

when something is being dropped to WordPad, WordPad window is on top with focus and text is added. In Eclipse editor text is pasted, Eclipse window gains focus and is on top.

When I implement drag&drop using wxPython target window is not brought to front. I implemented drag&drop in similar way to (drag):

import wx

class DragFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None)
        self.tree = wx.TreeCtrl(self, wx.ID_ANY)
        root = self.tree.AddRoot("root item")
        self.tree.AppendItem(root, "child 1")
        self.tree.Bind(wx.EVT_TREE_BEGIN_DRAG, self.__onBeginDrag)        
    def __onBeginDrag(self, event):
        tdo = wx.PyTextDataObject(self.tree.GetItemText(event.GetItem()))
        dropSource = wx.DropSource(self.tree)
        dropSource.SetData(tdo)
        dropSource.DoDragDrop(True)

app = wx.PySimpleApp()
frame = DragFrame()
app.SetTopWindow(frame)
frame.Show()
app.MainLoop()

Second program (drop):

import wx
class TextDropTarget(wx.TextDropTarget):
    def __init__(self, obj):
        wx.TextDropTarget.__init__(self)
        self.obj = obj
    def OnDropText(self, x, y, data):
        self.obj.WriteText(data + '\n\n')
        wx.MessageBox("Error", "Error", style = wx.ICON_ERROR)

class DropFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None)
        text = wx.TextCtrl(self, wx.ID_ANY)
        text.SetDropTarget(TextDropTarget(text))

app = wx.PySimpleApp()
frame = DropFrame()
app.SetTopWindow(frame)
frame.Show()
app.MainLoop()

When you run both programs, place windows in the centre of the screen (part of drop window is visible), then drag a node from drag window to drop window - target window displays message box which isn't visible, target window is hidden behind source window.

How to implement drag&drop that will focus on the second (target) window? I've tried adding window.Show(), window.SetFocus(), even using some functions of WinAPI (through win32gui). I think there should be some standard way of doing this. What am I missing?

Upvotes: 2

Views: 1018

Answers (2)

Anurag Uniyal
Anurag Uniyal

Reputation: 88837

You need to do anything you want int DragOver method of DropTarget e.g. there you can raise and set focus on your window

sample working code for target

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

    def OnDropText(self, x, y, data):
        self.obj.WriteText(data + '\n\n')
        wx.MessageBox("Error", "Error", style = wx.ICON_ERROR)

    def OnDragOver(self, *args):
        wx.CallAfter(self._callback)
        return wx.TextDropTarget.OnDragOver(self, *args)

class DropFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None)
        text = wx.TextCtrl(self, wx.ID_ANY)
        text.SetDropTarget(TextDropTarget(text, self._callback))

    def _callback(self):
        self.Raise()
        self.SetFocus()

app = wx.PySimpleApp()
frame = DropFrame()
app.SetTopWindow(frame)
frame.Show()
app.MainLoop()

Upvotes: 1

Esteban Küber
Esteban Küber

Reputation: 36852

Wouldn't this work?

class DropFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None)
        text = wx.TextCtrl(self, wx.ID_ANY)
        self.SetFocus() # Set's the focus to this window, allowing it to receive keyboard input.
        text.SetDropTarget(TextDropTarget(text))

wx.Frame inherits from wx.Window, that has SetFocus(self).


I have just tested it and it works. Just moved SetFocus before SetDropTarget, as its a cleaner behavior.

Upvotes: 1

Related Questions