【问题标题】:Scrolling through a `wx.ScrolledPanel` with the mouse wheel and arrow keys使用鼠标滚轮和箭头键滚动 `wx.ScrolledPanel`
【发布时间】:2010-11-11 23:11:11
【问题描述】:

在我的 wxPython 应用程序中,我创建了一个 wx.ScrolledPanel,其中有一个大的 wx.StaticBitmap 需要滚动。

滚动条确实出现了,我可以用它们滚动,但我也希望能够用鼠标滚轮和键盘上的箭头键滚动。如果“Home”、“Page Up”和其他键也能按预期工作,那就太好了。

我该怎么做?

更新:

我看到了问题。 ScrolledPanel 能够滚动,但只有在它处于焦点时才能滚动。问题是,我如何才能成为焦点?即使点击它也不会这样做。只有当我在其中放置一个文本控件时,我才能专注于它,从而使用滚轮滚动。但我不想在其中包含文本控件。那么如何让它成为焦点呢?

更新 2:

这是一个显示这种现象的代码示例。取消注释以查看文本控件如何使鼠标滚轮起作用。

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()

【问题讨论】:

    标签: python user-interface wxpython scroll


    【解决方案1】:

    问题在于窗口框架获得焦点,子面板没有获得焦点(在 ubuntu linux 上它工作正常)。解决方法可以像重定向 Frame 焦点事件以将焦点设置到面板一样简单,例如

    import wx, wx.lib.scrolledpanel
    
    class MyFrame(wx.Frame):
        def __init__(self, *args, **kwargs):
            wx.Frame.__init__(self, *args, **kwargs)
    
            self.panel = 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)
    
            scrolled_panel.SetSizer(sizer)
    
            self.Show()
    
            self.panel.SetFocus()
            scrolled_panel.Bind(wx.EVT_SET_FOCUS, self.onFocus)
    
        def onFocus(self, event):
            self.panel.SetFocus()
    
    if __name__=="__main__":
        app = wx.PySimpleApp()
        my_frame=MyFrame(None, -1)
        app.MainLoop()
    

    或鼠标移到面板上,将焦点设置为它,所有键+鼠标滚轮将开始工作,例如

    import wx, wx.lib.scrolledpanel
    
    class MyFrame(wx.Frame):
        def __init__(self, *args, **kwargs):
            wx.Frame.__init__(self, *args, **kwargs)
    
            self.panel = scrolled_panel = \
                wx.lib.scrolledpanel.ScrolledPanel(parent=self, id=-1)
            scrolled_panel.SetupScrolling()
    
            scrolled_panel.Bind(wx.EVT_MOTION, self.onMouseMove)
    
            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)
    
            scrolled_panel.SetSizer(sizer)
    
            self.Show()
    
        def onMouseMove(self, event):
            self.panel.SetFocus()
    
    if __name__=="__main__":
        app = wx.PySimpleApp()
        my_frame=MyFrame(None, -1)
        app.MainLoop()
    

    【讨论】:

    • 关于您的第一个代码示例,它不能用于多个 ScrolledPanel,对吗?关于您的第二个代码示例,我认为这是要走的路。 (除了不那么敏感之外,我不希望每次你不小心将鼠标悬停在面板上时焦点都会改变。)我想我会继承 ScrolledPanel 并将其发布在这里。
    • 滚动面板应该是焦点,但是如果你不喜欢鼠标移动的焦点,你可以在点击时做同样的事情
    【解决方案2】:

    我希望这是一个应该做你想做的事的例子。 (编辑:回想起来,这并不完全有效,例如,当有两个滚动面板时......我会把它留在这里,但这样人们可以否决它或其他什么。)基本上我将所有内容放在框架内的面板中(通常是个好主意),然后将焦点设置到此主面板。

    import wx
    import wx, wx.lib.scrolledpanel
    
    class MyFrame(wx.Frame):
        def __init__(self, *args, **kwargs):
            wx.Frame.__init__(self, *args, **kwargs)
            main_panel = wx.Panel(self, -1)
            main_panel.SetBackgroundColour((150, 100, 100))
            self.main_panel = main_panel
    
            scrolled_panel = \
                wx.lib.scrolledpanel.ScrolledPanel(parent=main_panel, id=-1)
            scrolled_panel.SetupScrolling()
            self.scrolled_panel = scrolled_panel
    
            cpanel = wx.Panel(main_panel, -1)
            cpanel.SetBackgroundColour((100, 150, 100))
            b = wx.Button(cpanel, -1, size=(40,40))
            self.Bind(wx.EVT_BUTTON, self.OnClick, b)
            self.b = b
    
            text = "Ooga booga\n" * 50
            static_text=wx.StaticText(scrolled_panel, -1, text)
            main_sizer=wx.BoxSizer(wx.VERTICAL)
            main_sizer.Add(scrolled_panel, 1, wx.EXPAND)
            main_sizer.Add(cpanel, 1, wx.EXPAND)
            main_panel.SetSizer(main_sizer)
    
            text_sizer=wx.BoxSizer(wx.VERTICAL)
            text_sizer.Add(static_text, 1, wx.EXPAND)
            scrolled_panel.SetSizer(text_sizer)
    
            self.main_panel.SetFocus()
    
            self.Show()
    
        def OnClick(self, evt):
            print "click"
    
    
    if __name__=="__main__":
        class MyApp(wx.App):
    
            def OnInit(self):
                frame = MyFrame(None, -1)
                frame.Show(True)
                self.SetTopWindow(frame)
                return True
        app = MyApp(0)
        app.MainLoop()
    

    对于键盘控制,例如从 home 键设置操作,我认为您需要绑定到这些事件,并做出适当的响应,例如使用 mypanel.Scroll(0,0) 作为 home 键(并记得调用 @987654324 @ 用于您不采取行动的键盘事件)。 (编辑:我不认为有任何默认的滚动键绑定。我不确定我是否想要任何一个,例如,如果滚动面板中有一个滚动面板会发生什么面板?)

    【讨论】:

    • 但是放在哪里呢?我可能想将焦点更改为其他一些小部件,然后再次返回到 ScrolledPanel。
    • 1.请参阅我的第一条评论中的问题。 2. 是的,我已经调用了 SetupScrolling。 3.我真的需要用home键重新发明轮子吗? wxPython 没有实现这个吗?
    • 有些奇怪。例如在 wxPython 演示中,当鼠标悬停在每个面板上时,该面板将随滚轮滚动。所以有几个问题。如果你打电话给SetFocus 可以吗?如果您尝试以正常方式滚动,通过单击滚动条并移动,它会移动吗?如果你立即使用滚轮,它会起作用吗?
    • 1.我在检查它时遇到了麻烦,正在处理它。 2. 是的。 3.没有。
    • 似乎有其他事情正在引起关注,可能更值得弄清楚这是什么以及为什么而不是花时间在 SetFocus 上。如果没有一段代码可以模仿这种行为,我对此毫无想法。
    猜你喜欢
    • 2011-09-29
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 2017-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多