[ScrolledPanel] wx.EVT_CHILD_FOCUS for a Panel with own childs

I am using ScrolledPanel.
When I add some wx.Button (for testing) to it and do SetFocus() on each
of them ScrolledPanel.OnChildFocus() is called and the ScrolledPanel
scroll itself to the last added button.

But I am using my own "control"s there. The "control" is a Panel with
some childs (SpinCtrl, Button, ...). When I call SetFocus() in the
Panels OnChildFocus() is not called. The focus is set to the first
child of the Panel.

As a workaround I call ScrolledPanel.ScrollChildIntoView() by myself.

But is there a more elegant way? I am not sure how to handle that.
Maybe my own "control" (the Panel) should do some
event-handling/fireing so that its parent (the ScrolledPanel).
I can not find out who Bind() wx.EVT_CHILD_FOCUS to the scrolledPanel.
I am not getting into the topic completely.

Here is some example code

[code]
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import wx
import wx.lib.scrolledpanel

class MyPanel(wx.Panel):
    def __init__(self, parent):
        super(wx.Panel, self).__init__(parent)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(wx.Choice(self, choices=['a', 'b']))
        sizer.Add(wx.TextCtrl(self, value=str(id(self))))
        self.SetSizer(sizer)

class MyFrame(wx.Frame):
    def __init__(self):
        super(wx.Frame, self).__init__(None)
        sizer = wx.BoxSizer(wx.VERTICAL)

        bt = wx.Button(self, label='Test Add')
        bt.Bind(wx.EVT_BUTTON, self._OnAdd)
        sizer.Add(bt)

        self.panel = wx.lib.scrolledpanel.ScrolledPanel(self,
        style=wx.TAB_TRAVERSAL) self.panelsizer =
        wx.BoxSizer(wx.VERTICAL)

        i = 0
        while i < 20:
            self.panelsizer.Add(MyPanel(self.panel))
            i += 1

        self.panel.SetSizer(self.panelsizer)
        self.panel.SetupScrolling()

        sizer.Add(self.panel, proportion=1, flag=wx.EXPAND)
        self.SetSizer(sizer)

    def _OnAdd(self, event):
        focus = MyPanel(self.panel)
        self.panelsizer.Add(focus)

        self.Layout()
        # this alone doesn't work
        focus.SetFocus()
        # this is the workaround
        self.panel.ScrollChildIntoView(focus)

if __name__ == '__main__':
    app = wx.App()
    win = MyFrame()
    win.Show()
    app.MainLoop()
[/code]

JFYI: I commented your workaround out and tried it on Win7 64 bit with
Py 2.7.9 32bit / Wx 3.0.2.0 classic and

Py 3.4.3 32 bit / Wx 3.0.3.dev1820+49a8884 phoenix.

On both versions the scrolledpanel scrolls to the newly added items.

Which code did you used?

···

On 2015-05-04 09:29 Torsten <topic2k@googlemail.com> wrote:

JFYI: I commented your workaround out and tried it

I used the code from your second post:
#!/usr/bin/env python3

-- coding: utf-8 --

import wx
import wx.lib.scrolledpanel

class MyPanel(wx.Panel):
def init(self, parent):
super(wx.Panel, self).init(parent)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(wx.Choice(self, choices=[‘a’, ‘b’]))
sizer.Add(wx.TextCtrl(self, value=str(id(self))))
self.SetSizer(sizer)

class MyFrame(wx.Frame):
def init(self):
super(wx.Frame, self).init(None)
sizer = wx.BoxSizer(wx.VERTICAL)

    bt = wx.Button(self, label='Test Add')
    bt.Bind(wx.EVT_BUTTON, self._OnAdd)
    sizer.Add(bt)

    self.panel = wx.lib.scrolledpanel.ScrolledPanel(self,
    style=wx.TAB_TRAVERSAL) self.panelsizer =
    wx.BoxSizer(wx.VERTICAL)

    i = 0
    while i < 20:
        self.panelsizer.Add(MyPanel(self.panel))
        i += 1

    self.panel.SetSizer(self.panelsizer)
    self.panel.SetupScrolling()

    sizer.Add(self.panel, proportion=1, flag=wx.EXPAND)
    self.SetSizer(sizer)

def _OnAdd(self, event):
    focus = MyPanel(self.panel)
    self.panelsizer.Add(focus)

    self.Layout()
    # this alone doesn't work
    focus.SetFocus()
    # this is the workaround
    #self.panel.ScrollChildIntoView(focus)

if name == ‘main’:
app = wx.App()
win = MyFrame()
win.Show()
app.MainLoop()

``

Bug-Report: <http://trac.wxwidgets.org/ticket/16983>