PDA

Ver la versión completa : [Ayuda] Programa en wxpython



Dullyboy
20/08/2012, 19:02
¿Alguien sabe programar en wxpython? Porque estoy intentado hacerme un programa para salvar archivos y configuraciones y de paso aprender, pero hay cosas que no estoy siendo capaz de encontrar como solucionar.
Tengo un Frame principal que contiene 2 splitters para meter 3 paneles, definidos por separado, y querría que, con eventos y variables del el panel A, se actualizase el panel B ¿es posible o tendría que ponerlo todo junto?
El programa debería de salvar los datos de la ejecución anterior y recuperarlos al inicio ¿cuál es la mejor forma de guardar listas?

Gracias.

swapd0
20/08/2012, 19:20
Yo programo con las wxWidgets pero en C++

Se supone que cuando mandas un evento este va "hacia arriba" siguiendo la jerarquia de ventanas.

Los eventos que lance los paneles primero se intentarian capturar en el propio panel, si no son capturados se pasaria a la ventana padre, en este caso los splitters, si no se capturan a la ventana padre que seria el frame. Lo normal es capturar los eventos que te interesen en el frame y modificar lo que corresponda.

Dullyboy
20/08/2012, 23:16
Lujo funciona, había estado intentado de todo, y como soy un chapuzas, había probado a que capturase el evento en el frame sin haber borrado que capturase en el panel, y claro, solo hacía la salida del panel. Gracias tio, me has ahorrado comerme mucho la cabeza :D.

Dullyboy
23/08/2012, 16:35
Ahora lo que no encuentro es como actualizar el panel a partir del evento :).

swapd0
23/08/2012, 20:00
No tengo ni idea de python pero espero que entiendas la explicacion.

Lo normal es que en el constructor del frame crees los paneles y los guardes en varibles miembro de la clase que herede de frame. Despues en los eventos del frame, con acceder a estas variables tienes acceso a los paneles y puedes hacer todas las guarrerias que quieras. En C++ seria asi.



class MiFrame : public wxFrame
{
public:
MiFrame(...) : wxFrame(...)
{
...
mPanelA = new PanelA(...);
mPanelB = new PanelB(...);
...
// ahora añadiria los paneles a los distintos sizers para que esten alineados correctamente
}
...
protected:
PanelA *mPanelA
PanelB *mPanelB;

void OnEventoFoo(wxCommanEvent &)
{
// actualizo el panel A
mPanelA->insertaDatos(...);
}

void OnEventoBar(wxCommanEvent &)
{
// actualizo el panel B
mPanelB->leeDatos(...);
}
}


Por supuesto al crear los paneles le tienes que pasar un id concreto (no el wxID_ANY) y despues en la tabla de eventos conectas el id con el metodo correspondiente(wxEvento...)

Dullyboy
24/08/2012, 10:31
Lo entiendo por encima un poco :). Yo es que tengo los paneles definidos como otras clases (no tengo ni idea de si es mejor peor o directamente no se puede hacer teniendolos así, pero fue lo que vi por ejemplos y me resulta más ordenado para empezar). Me había hecho un ejemplo mínimo para preguntar en stackoverflow:

from wx.lib.pubsub import Publisher
import wx

global name
name = 'none, please select an item'

class PanelA(wx.Panel):
def __init__(self, parent, name):
wx.Panel.__init__(self, parent)
self.hbox = wx.BoxSizer(wx.HORIZONTAL)
self.vbox = wx.BoxSizer(wx.VERTICAL)
str = name
txt = wx.StaticText(self, -1, "You have selected " + str, (20, 100))
self.hbox.Add(txt, 1, wx.EXPAND | wx.ALL, 20)

class PanelB(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)

self.hbox = wx.BoxSizer(wx.HORIZONTAL)
self.vbox = wx.BoxSizer(wx.VERTICAL)

self.listbox = wx.ListBox(self, -1)
self.hbox.Add(self.listbox, 1, wx.EXPAND | wx.ALL, 20)

self.btnPanel = wx.Panel(self, -1)
self.new = wx.Button(self.btnPanel,label='Add', size=(90, 30))
self.new.Bind(wx.EVT_BUTTON, self.NewItem)

self.vbox.Add((-1, 20))
self.vbox.Add(self.new)

self.btnPanel.SetSizer(self.vbox)
self.hbox.Add(self.btnPanel, 0.6, wx.EXPAND | wx.RIGHT, 20)
self.SetSizer(self.hbox)

self.Bind(wx.EVT_LISTBOX, self.onSelect)

def onSelect(self, event):
name_selected = self.listbox.GetStringSelection()
Publisher().sendMessage(("ListBox"), name_selected)

def NewItem(self, event):
text = wx.GetTextFromUser('Nombre', 'Programa a salvar')
if text != '':
self.listbox.Append(text)

class MainFrame(wx.Frame):
def __init__(self, parent, id, title, *args, **kw):

wx.Frame.__init__(self, parent, id, title, size = (800,300))

self.splitter = wx.SplitterWindow(self, -1, style=wx.SP_3D)

self.lc1 = PanelB(self.splitter)
self.lc2 = PanelA(self.splitter, name)
self.splitter.SplitVertically(self.lc1, self.lc2)

Publisher().subscribe(self.OnSelect, ("ListBox"))

sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(self.splitter, 1, wx.EXPAND)
self.SetSizer(sizer)

self.Centre()
self.Show(True)

def OnSelect(self, name_selected):
name = name_selected
#I stucked here

if __name__ == "__main__":
app = wx.App()
frame = MainFrame(None,-1,'Mi aplicacion')
app.MainLoop()
Leyendo lo que has puesto y buscando por stackoverflow he llegado a ver que puedo modificar el valor del panel simplemente esciribendolo como subvariable, self.lc2.str = name, (no me daba la cabeza para pensar que fuese posible :D), pero no encuentro la manera de hacer que se actualice el panel.

EDIT:
No encuentro manera de hacerlo como dices, pero con la ayuda de uno de stackoverflow he llegado a una gitanada que puede funcionar :D. Básicamente meterle una función al panel A que se encarge de actualizarlo y llamarla desde el Frame. Eso sí, muchas gracias por la ayuda.

swapd0
24/08/2012, 19:40
¿Has probado a llamar al metodo Refresh del panel (esta definido en wxWindow que es la clase padre de wxPanel)?

Dullyboy
24/08/2012, 19:50
¿Has probado a llamar al metodo Refresh del panel (esta definido en wxWindow que es la clase padre de wxPanel)?

Sí, junto con Layout() (este lo tengo que usar ahora para que dibuje bien la actualización del panel) y Update() los había probado y no había conseguido nada con ninguno.