2008-11-07 7 views
2

J'essaie d'apprendre Python et WxPython. Je suis programmeur SAS depuis des années. Ce truc OOP se rapproche lentement mais je suis toujours flou sur beaucoup de concepts. Voici une section de code. J'essaye d'employer un clic de bouton pour créer une instance d'une autre classe. Plus précisément, j'ai mon panneau principal dans une classe et je voulais utiliser un panneau secondaire lorsqu'un utilisateur cliquait sur l'un des éléments du menu sur le panneau principal. J'ai fait tout ce travail lorsque le panneau secondaire était juste une fonction. Je n'arrive pas à faire travailler ti en classe.Comment créer une instance d'une classe dans une autre classe en Python

Voici le code

import wx 

class mainPanel(wx.Frame): 
    def __init__(self, parent, id, title): 
    wx.Frame.__init__(self, parent, id, 'directEDGAR Supplemental Tools', size=(450, 450)) 
    wx.Panel(self,-1) 
    wx.StaticText(self,-1, "This is where I will describe\n the purpose of these tools",(100,10)) 


    menubar = wx.MenuBar() 
    parser = wx.Menu() 
    one =wx.MenuItem(parser,1,'&Extract Tables with One Heading or Label') 
    two =wx.MenuItem(parser,1,'&Extract Tables with Two Headings or Labels') 
    three =wx.MenuItem(parser,1,'&Extract Tables with Three Headings or Labels') 
    four =wx.MenuItem(parser,1,'&Extract Tables with Four Headings or Labels') 
    quit = wx.MenuItem(parser, 2, '&Quit\tCtrl+Q') 
    parser.AppendItem(one) 
    parser.AppendItem(two) 
    parser.AppendItem(three) 
    parser.AppendItem(four) 
    parser.AppendItem(quit) 
    menubar.Append(parser, '&Table Parsers') 

    textRip = wx.Menu() 
    section =wx.MenuItem(parser,1,'&Extract Text With Section Headings') 
    textRip.AppendItem(section) 
    menubar.Append(textRip, '&Text Rippers') 

    dataHandling = wx.Menu() 
    deHydrate =wx.MenuItem(dataHandling,1,'&Extract Data from Tables') 
    dataHandling.AppendItem(deHydrate) 
    menubar.Append(dataHandling, '&Data Extraction')   


    self.Bind(wx.EVT_MENU, self.OnQuit, id=2) 

c'est là, je pense que je suis être intelligent en utilisant un bouton clic pour créer une instance

de SUBPANEL.

self.Bind(wx.EVT_MENU, self.subPanel(None, -1, 'TEST'),id=1) 

    self.SetMenuBar(menubar) 

    self.Centre() 
    self.Show(True) 

    def OnQuit(self, event): 
    self.Close() 

class subPanel(wx.Frame): 
    def __init__(self, parent, id, title): 
    wx.Frame.__init__(self, parent, id, 'directEDGAR Supplemental Tools', size=(450, 450)) 
    wx.Panel(self,-1) 
    wx.StaticText(self,-1, "This is where I will describe\n the purpose of these tools",(100,10)) 


    getDirectory = wx.Button(panel, -1, "Get Directory Path", pos=(20,350)) 
    getDirectory.SetDefault() 

    getTerm1 = wx.Button(panel, -1, "Get Search Term", pos=(20,400)) 
    getTerm1.SetDefault() 

    #getDirectory.Bind(wx.EVT_BUTTON, getDirectory.OnClick, getDirectory.button) 


    self.Centre() 
    self.Show(True) 




app = wx.App() 
mainPanel(None, -1, '') 
app.MainLoop() 
+0

Le Le morceau de code supérieur ne se met pas correctement en retrait. –

+0

Juste pour obtenir votre terminologie droite; Votre question n'a pas de sens - Vous auriez dû demander "Comment créer une instance d'une classe dans une autre instance, en Python". La distinction entre classe et objet est importante. – troelskn

Répondre

0

Vous avez besoin d'un gestionnaire d'événements dans votre expression de liaison

self.bind(wx.EVT_MENU, subPanel(None, -1, 'TEST'),id=1) 

doit être changé pour:

self.bind(wx.EVT_MENU, <event handler>, <id of menu item>) 

où votre gestionnaire d'événements répond à l'événement et instancie le sous-panneau:

def OnMenuItem(self, evt): #don't forget the evt 
    sp = SubPanel(self, wx.ID_ANY, 'TEST') 
    #I assume you will add it to a sizer 
    #if you aren't... you should 
    test_sizer.Add(sp, 1, wx.EXPAND) 
    #force the frame to refresh the sizers: 
    self.Layout() 

Vous pouvez également instancier le sous-panneau de votre cadre __init__ et appeler un subpanel.Hide() après instanciation, puis votre gestionnaire d'événements menuitem et appeler un spectacle sur le panneau subpanel.Show()

Edit: Voici un code qui fera ce que je pense que vous demandez:

#!usr/bin/env python 

import wx 

class TestFrame(wx.Frame): 
    def __init__(self, parent, *args, **kwargs): 
     wx.Frame.__init__(self, parent, *args, **kwargs) 
     framesizer = wx.BoxSizer(wx.VERTICAL) 
     mainpanel = MainPanel(self, wx.ID_ANY) 
     self.subpanel = SubPanel(self, wx.ID_ANY) 
     self.subpanel.Hide() 
     framesizer.Add(mainpanel, 1, wx.EXPAND) 
     framesizer.Add(self.subpanel, 1, wx.EXPAND) 
     self.SetSizerAndFit(framesizer) 

class MainPanel(wx.Panel): 
    def __init__(self, parent, *args, **kwargs): 
     wx.Panel.__init__(self, parent, *args, **kwargs) 
     panelsizer = wx.BoxSizer(wx.VERTICAL) 
     but = wx.Button(self, wx.ID_ANY, "Add") 
     self.Bind(wx.EVT_BUTTON, self.OnAdd, but) 
     self.panel_shown = False 
     panelsizer.Add(but, 0) 
     self.SetSizer(panelsizer) 

    def OnAdd(self, evt): 
     if not self.panel_shown: 
      self.GetParent().subpanel.Show() 
      self.GetParent().Fit() 
      self.GetParent().Layout() 
      self.panel_shown = True 
     else: 
      self.GetParent().subpanel.Hide() 
      self.GetParent().Fit() 
      self.GetParent().Layout() 
      self.panel_shown = False 

class SubPanel(wx.Panel): 
    def __init__(self, parent, *args, **kwargs): 
     wx.Panel.__init__(self, parent, *args, **kwargs) 
     spsizer = wx.BoxSizer(wx.VERTICAL) 
     text = wx.StaticText(self, wx.ID_ANY, label='I am a subpanel') 
     spsizer.Add(text, 1, wx.EXPAND) 
     self.SetSizer(spsizer) 

if __name__ == '__main__': 
    app = wx.App() 
    frame = TestFrame(None, wx.ID_ANY, "Test Frame") 
    frame.Show() 
    app.MainLoop() 
1

Je ne sais pas wxWidgets, mais d'après ce que je sais de Python, je devine que vous devez changer:

self.Bind(wx.EVT_MENU, self.subPanel(None, -1, 'TEST'),id=1) 

à:

self.Bind(wx.EVT_MENU, subPanel(None, -1, 'TEST'),id=1) 

" subPanel "est une classe définie globalement, pas un membre de" self "(qui est un mainPanel). Edit: Ah, "Bind" semble lier une action à une fonction, vous devez donc lui donner une fonction qui crée l'autre classe. Essayez ce qui suit. Cela ne fonctionne toujours pas, mais au moins, il se bloque maintenant lors de la création de subPanel.

self.Bind(wx.EVT_MENU, lambda(x): subPanel(None, -1, 'TEST'),id=1) 
1

Vous devez gérer le bouton événement click, et créer le panneau dans votre gestionnaire de bouton (comme vous le faites déjà avec votre méthode de OnQuit).

Je pense que le code suivant fait ce que vous recherchez: crée un nouveau cadre lorsque vous cliquez sur le bouton/l'élément de menu est sélectionné.

import wx 

class MyFrame(wx.Frame): 
    def __init__(self, parent, title="My Frame", num=1): 

     self.num = num 
     wx.Frame.__init__(self, parent, -1, title) 
     panel = wx.Panel(self) 

     button = wx.Button(panel, -1, "New Panel") 
     button.SetPosition((15, 15)) 
     self.Bind(wx.EVT_BUTTON, self.OnNewPanel, button) 
     self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) 

     # Now create a menu 
     menubar = wx.MenuBar() 
     self.SetMenuBar(menubar) 

     # Panel menu 
     panel_menu = wx.Menu() 

     # The menu item 
     menu_newpanel = wx.MenuItem(panel_menu, 
            wx.NewId(), 
            "&New Panel", 
            "Creates a new panel", 
            wx.ITEM_NORMAL) 
     panel_menu.AppendItem(menu_newpanel) 

     menubar.Append(panel_menu, "&Panels") 
     # Bind the menu event 
     self.Bind(wx.EVT_MENU, self.OnNewPanel, menu_newpanel) 

    def OnNewPanel(self, event): 
     panel = MyFrame(self, "Panel %s" % self.num, self.num+1) 
     panel.Show() 

    def OnCloseWindow(self, event): 
     self.Destroy() 

def main(): 
    application = wx.PySimpleApp() 
    frame = MyFrame(None) 
    frame.Show() 
    application.MainLoop() 

if __name__ == "__main__": 
    main() 

Modifier: Ajout de code pour ce faire à partir d'un menu.