2009-07-18 15 views
5

En mi aplicación wxPython he creado un wx.ScrolledPanel, en el que hay que desplazar un gran wx.StaticBitmap.Desplazarse por un `wx.ScrolledPanel` con la rueda del mouse y las teclas de flecha

Aparecen las barras de desplazamiento y puedo desplazarme con ellas, pero también me gustaría poder desplazarme con la rueda del mouse y las teclas de flecha del teclado. Sería bueno si el "Inicio", "RePág", y esas otras teclas también funcionarían como se esperaba.

¿Cómo puedo hacer esto?

ACTUALIZACIÓN:

veo el problema. ScrolledPanel puede desplazarse, pero solo cuando está enfocado. El problema es, ¿cómo puedo estar enfocado? Incluso hacer clic en él no lo hace. Solo si pongo un control de texto dentro de él puedo enfocarme en él y así desplazarme con la rueda. Pero no quiero tener un control de texto en él. Entonces, ¿cómo lo hago enfocar?

ACTUALIZACIÓN 2:

Aquí está un ejemplo de código que muestra este fenómeno. Descomente para ver cómo un control de texto hace que la rueda del mouse funcione.

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

Respuesta

0

Aquí hay un ejemplo que debería hacer lo que quiera, espero. (Edit: En retrospectiva, esto no funciona, por ejemplo, cuando hay dos paneles desplazados ... Lo dejaré aquí para que peole pueda rechazarlo o lo que sea). Básicamente puse todo en un panel dentro del marco (generalmente una buena idea), y luego establece el foco en este panel principal.

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

Para el control del teclado, como el establecimiento de la acción de la tecla de inicio, creo que necesita para unirse a esos eventos, y responder de manera apropiada, como el uso de la clave mypanel.Scroll(0,0)home (y recuerde llamar para evt.Skip() los eventos de teclado en los que no actúa). (Editar: No creo que haya ningún enlace de teclas predeterminado para desplazarse. No estoy seguro de querer, ya sea, por ejemplo, ¿qué pasaría si hubiera un panel desplazado dentro de un panel desplazado?)

+0

¿Pero dónde ponerlo? Es posible que desee cambiar el foco a algún otro widget, y luego regresar al ScrolledPanel nuevamente. –

+0

1. Ver la pregunta en mi primer comentario. 2. Sí, he llamado a SetupScrolling. 3. ¿Realmente necesito reinventar la rueda con la tecla de inicio? ¿WxPython no implementa esto? –

+0

Algo es extraño. Por ejemplo, en la demostración de wxPython, cuando el mouse está sobre cada panel, ese panel se desplazará con la rueda. Entonces algunas preguntas Si llama a 'SetFocus', ¿funciona? Si intenta desplazarse de la manera normal, haciendo clic en la barra de desplazamiento y moviéndose, ¿se mueve? Y si inmediatamente usa la rueda de desplazamiento, ¿funciona entonces? – tom10

3

El problema está en la ventana El recuadro obtiene el foco y el panel secundario no obtiene el Enfoque (en ubuntu linux funciona bien). La solución puede ser tan simple como redirigir el evento de enfoque de fotogramas para establecer el foco en el panel, p.

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

o onmouse moverse sobre el panel, establecer el foco en él, y todas las teclas + mousewheeel comenzarán a trabajar, por ejemplo,

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

En cuanto a su primer ejemplo de código, no funcionará para más de un ScrolledPanel, ¿o sí? En cuanto a su segunda muestra de código, creo que este es el camino a seguir. (Excepto un poco menos sensible, no quiero que el foco cambie cada vez que pasas accidentalmente sobre el panel.) Creo que voy a subclasificar ScrolledPanel y lo publicaré aquí. –

+1

para desplazarse por un panel, debe estar enfocado, pero si no le gusta centrarse en mover el mouse, puede hacer lo mismo al hacer clic –

Cuestiones relacionadas