Wie kann ich eine Instanz einer Klasse in einer anderen Klasse in Python erstellen
Frage
Ich versuche, Python und WxPython zu lernen. Ich habe ein SAS-Programmierer seit Jahren. Dieses OOP Zeug kommt langsam zusammen, aber ich bin immer noch unscharf auf viele der Konzepte. Unten ist ein Codeabschnitt. Ich versuche, einen Button-Klick zu verwenden, um eine Instanz einer anderen Klasse zu erstellen. Speziell-Ich habe mein Hauptfeld in einer Klasse, und ich wollte ein Sekundärfeld zu Beispiel, wenn ein Benutzer auf einem der Menüpunkte auf dem Hauptfeld angeklickt. Ich habe all diese Arbeit, wenn das Sekundärfeld nur eine Funktion war. Ich kann nicht scheinen, ti als Klasse zu arbeiten.
Hier ist der 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)
das ist, wo ich denke, ich bin klug ist, um eine Schaltfläche klicken, um eine Instanz zu erstellen, indem Sie mit
von 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()
Lösung
Sie müssen einen Event-Handler in Ihrem binden Ausdruck
self.bind(wx.EVT_MENU, subPanel(None, -1, 'TEST'),id=1)
geändert werden muss, um:
self.bind(wx.EVT_MENU, <event handler>, <id of menu item>)
, wo Ihre Event-Handler auf das Ereignis reagiert und instanziiert das subpanel:
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()
Alternativ können Sie die Blendenhalterung in Ihrem Rahmen des __init__
instanziiert und eine subpanel.Hide()
nach der Instanzierung aufrufen und Ihre menuitem Ereignishandler dann und eine Show auf dem Panel subpanel.Show()
rufen
Edit: Hier ist ein Code, der das tut, was ich denke, dass Sie fragen:
#!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()
Andere Tipps
Ich weiß nicht, wxWidgets, sondern auf das, was ich von Python wissen, ich vermute, dass Sie ändern müssen:
self.Bind(wx.EVT_MENU, self.subPanel(None, -1, 'TEST'),id=1)
zu:
self.Bind(wx.EVT_MENU, subPanel(None, -1, 'TEST'),id=1)
„SUBPANEL“ ist eine global definierte Klasse, kein Mitglied der „Selbst“ (das ein Mainpanel).
Edit: Ah, „Bind“ scheint eine Aktion auf eine Funktion zu binden, so müssen Sie es eine Funktion geben, die die andere Klasse erstellt. Versuche Folgendes. Es funktioniert immer noch nicht, aber zumindest stürzt jetzt während der SUBPANEL Schöpfung.
self.Bind(wx.EVT_MENU, lambda(x): subPanel(None, -1, 'TEST'),id=1)
Sie sollten die Schaltfläche Click-Ereignis, Griff und die Platte in Ihrem Tastenhandler erstellen (wie Sie bereits mit Ihrer OnQuit Methode tun).
Ich denke, der folgende Code im Grunde tut, was sind Sie nach -. Einen neuen Rahmen erstellt, wenn die Schaltfläche geklickt wird / Menüpunkt ausgewählt wird,
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()
Bearbeiten :. Code hinzugefügt diese aus einem Menü zu tun