Scrolling wx.ScrolledPanel with the mouse wheel, arrow keys, and PgUp/PgDn buttons

614 views
Skip to first unread message

cool-RR

unread,
Jul 18, 2009, 5:23:57 PM7/18/09
to wxPython-users
Hello everyone,

I have a problem:
In my wxPython application I've created a wx.ScrolledPanel, in which
there is a big wx.StaticBitmap that needs to be scrolled.

The scroll bars do appear and I can scroll with them, but I'd also
like to be able to scroll with the mouse wheel and the arrow keys on
the keyboard. It would also be nice if the "Home", "Page Up", and
those other keys would function as expected.

I noticed that the mouse wheel does work when I place a wx.TextCtrl
inside the ScrolledPanel and focus on it. I guess this has something
to do with the focus.

So what do I do?

Thanks,
Ram.

cool-RR

unread,
Jul 19, 2009, 5:21:23 PM7/19/09
to wxPython-users
Anyone has a clue?

Steven Sproat

unread,
Jul 19, 2009, 5:29:07 PM7/19/09
to wxPytho...@googlegroups.com
for the middle mouse, check out the wx.lib.dragscroller and bind it to
the appropriate events
for home and end you'll have to do some calculations in relation to the
bitmap's size on the canvas

cool-RR

unread,
Jul 19, 2009, 6:16:11 PM7/19/09
to wxPython-users
Is this necessary? I see that ScrolledPanel already has the
functionality to support the mouse wheel, the problem is that it's
only being used when there is a text control in it. Can't I make it
work without a text control?

cool-RR

unread,
Jul 20, 2009, 7:27:28 AM7/20/09
to wxPython-users
Here is a code sample that demonstrates this behavior:


##################################

import wx, wx.lib.scrolledpanel

class MyFrame(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)

scrolled_panel = \
wx.lib.scrolledpanel.ScrolledPanel(parent=self, id=-1)
scrolled_panel.SetupScrolling()

text = "Ooga booga\n" * 50
static_text=wx.StaticText(scrolled_panel, -1, text)
sizer=wx.BoxSizer(wx.VERTICAL)
sizer.Add(static_text, wx.EXPAND, 0)

# Uncomment the following 2 lines to see how adding
# a text control to the scrolled panel makes the
# mouse wheel work.
#
#text_control=wx.TextCtrl(scrolled_panel, -1)
#sizer.Add(text_control, wx.EXPAND, 0)

scrolled_panel.SetSizer(sizer)

self.Show()

if __name__=="__main__":
app = wx.PySimpleApp()
my_frame=MyFrame(None, -1)
#import cProfile; cProfile.run("app.MainLoop()")
app.MainLoop()

######################################

Robin Dunn

unread,
Jul 20, 2009, 5:38:43 PM7/20/09
to wxPytho...@googlegroups.com

It depends on platform, they have different native behaviors for the
wheel events. On Windows the wheel events are only sent to the widget
that has the focus. If you are on Windows then I guess that in this
case the native textctrl is passing them up to the parent.

On the other platforms the wheel events are sent to whichever widget the
mouse pointer is positioned over, (possibly even if that app is not in
the foreground.) So for scrolled panels you should be able to get the
wheel events if you position the pointer over some part of the scrolled
panel that is not covered by a child widget.

--
Robin Dunn
Software Craftsman
http://wxPython.org

cool-RR

unread,
Jul 20, 2009, 6:05:25 PM7/20/09
to wxPytho...@googlegroups.com

It depends on platform, they have different native behaviors for the
wheel events.  On Windows the wheel events are only sent to the widget
that has the focus.  If you are on Windows then I guess that in this
case the native textctrl is passing them up to the parent.

On the other platforms the wheel events are sent to whichever widget the
mouse pointer is positioned over, (possibly even if that app is not in
the foreground.)  So for scrolled panels you should be able to get the
wheel events if you position the pointer over some part of the scrolled
panel that is not covered by a child widget.

--
Robin Dunn

Why doesn't ScrolledPanel have the focus? Even clicking on it does not set it in focus! I tried calling SetFocus() from the code, and it does work and make the mouse wheel function, but the moment you click on anything the ScrolledPanel loses focus and there is no way to make it focused again through the GUI.
Do I need to subclass ScrolledPanel into something that takes focus more aggressively? Or is there a simpler solution built into wxPython?

Thanks,
Ram.

Robin Dunn

unread,
Jul 21, 2009, 2:25:08 PM7/21/09
to wxPytho...@googlegroups.com
cool-RR wrote:
>
>
> It depends on platform, they have different native behaviors for the
> wheel events. On Windows the wheel events are only sent to the widget
> that has the focus. If you are on Windows then I guess that in this
> case the native textctrl is passing them up to the parent.
>
> On the other platforms the wheel events are sent to whichever widget the
> mouse pointer is positioned over, (possibly even if that app is not in
> the foreground.) So for scrolled panels you should be able to get the
> wheel events if you position the pointer over some part of the scrolled
> panel that is not covered by a child widget.
>
> --
> Robin Dunn
>
>
> Why doesn't ScrolledPanel have the focus? Even clicking on it does not
> set it in focus! I tried calling SetFocus() from the code, and it does
> work and make the mouse wheel function, but the moment you click on
> anything the ScrolledPanel loses focus and there is no way to make it
> focused again through the GUI.

Because it derives from wx.Panel which has code that when it receives
the focus will try to reset the focus to its first child that will take
the focus. This is needed to make the tab-traversal work when there are
nested panels, panels in things like splitters or notebooks, etc..

> Do I need to subclass ScrolledPanel into something that takes focus more
> aggressively? Or is there a simpler solution built into wxPython?

The best thing to do, if possible, is to not have any child widgets on
the scrolled window. For example, instead of having a StaticBitmap
widget you can draw the bitmap yourself directly on the scrolled window.

Otherwise, I don't think that all of the focus handling and tab
traversal of wx.Panel/wx.ScrolledWindow can be overridden... Perhaps
instead you could add scrollability to wx.Window yourself without that
focus and navigation functionality.

Reply all
Reply to author
Forward
0 new messages