2008-11-07 2 views
2

Я пытаюсь изучить Python и WxPython. Я много лет работал программистом SAS. Этот материал ООП медленно приближается, но я все еще нечеткий по многим концепциям. Ниже приведен фрагмент кода. Я пытаюсь использовать кнопку, чтобы создать экземпляр другого класса. В частности, у меня есть моя основная панель в одном классе, и я хотел бы указать дополнительную панель, когда пользователь нажал на один из пунктов меню на главной панели. Я сделал всю эту работу, когда вторичная панель была просто функцией. Я не могу заставить себя работать как класс.Как создать экземпляр класса в другом классе в Python

Вот код

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) 

это, когда я думаю, что я лукавит с помощью кнопки нажмите, чтобы создать экземпляр

из ПОДСЕКЦИЯ.

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

Верхняя часть кода не отступает должным образом. – 2008-11-07 23:43:32

ответ

0

Вам нужен обработчик события в вашем выражении связывания

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

должен быть изменен на:

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

где обработчик события реагирует на события и конкретизирует субпанель:

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

В качестве альтернативы вы можете создать субпанель в вашем фрейме __init__ и вызвать subpanel.Hide() после конкретизации, а затем обработчик событий MENUITEM и вызвать шоу на панели subpanel.Show()

Edit: Вот некоторый код, который будет делать то, что я думаю, что вы спрашиваете:

#!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

Я не знаю WxWidgets, но на основе того, что я знаю Python, я предполагаю, что вам нужно изменить:

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

к:

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

" subPanel "является глобально определенным классом, а не членом" self "(который является mainPanel).

Редактировать: Ах, «Связывание», похоже, привязывает действие к функции, поэтому вам нужно дать ему функцию, которая создает другой класс. Попробуйте следующее. Он по-прежнему не работает, но по крайней мере он теперь сбой во время создания подпанели.

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

Вы должны обрабатывать событие нажатия кнопки, а также создать панель в обработчике кнопки (как вы уже делаете с вашим методом OnQuit).

Я думаю, что следующий код в основном делает то, что вам нужно, - создает новый кадр при нажатии кнопки или пункте меню.

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

Редактировать: Добавлен код, чтобы сделать это из меню.