问题描述
我有一个代码。当它运行时,您单击添加联系人按钮并添加一些联系人。当您按下每个联系人时,它只会显示您添加的最后一个联系人信息。但是,当我按下每个联系人时,我希望它显示我单击的联系人的信息。谁能帮我解决这个问题?
import wx
from wx._core import RB_GROUP,TE_READONLY
import sys
import os
from _ssl import nid2obj
class MyFrame(wx.Frame):
def __init__(self,parent,title):
wx.Frame.__init__(self,title=title,size=(500,500))
self.panel = wx.Panel(self,-1)
self.contactslist =[]
self.path = os.getcwd()+'\\contacts-db'
self.nc = wx.Button(self.panel,label='new contact')
self.nc.Bind(wx.EVT_BUTTON,self.newcontact)
self.displaycontacts()
self.Show(True)
def displaycontacts(self):
for roots,dirs,files in os.walk(self.path):
for filename in files:
#self.contactslist.append(filename)
self.cntct = wx.Button(self.panel,label=filename)
self.cntct.Bind(wx.EVT_BUTTON,self.clickcontacts)
def clickcontacts(self,e):
self.oc =self.path+'\\'+self.cntct.GetLabel()
self.oc2 = open(self.oc,'r')
prt = wx.TextCtrl(self.panel,value=self.oc2.read())
def newcontact(self,e):
self.val = ''
self.f1 = wx.TextCtrl(self.panel,value='enter your first name',pos=(0,0))
self.f1.SetFocus()
self.f2 = wx.TextCtrl(self.panel,value='enter your last name',50))
self.rbm = wx.RadioButton(self.panel,label='male',style=RB_GROUP,100))
self.rbm.Bind(wx.EVT_RAdioBUTTON,self.male)
self.rbf = wx.RadioButton(self.panel,label='female')
self.rbf.Bind(wx.EVT_RAdioBUTTON,self.female)
self.btn = wx.Button(self.panel,label='show',200))
self.btn.Bind(wx.EVT_BUTTON,self.showform)
self.s = wx.TextCtrl(self.panel,value=self.val,style=wx.TE_MULTILINE,size=(800,800))
self.clrbtn = wx.Button(self.panel,label='clear',pos=(800,800))
self.clrbtn.Bind(wx.EVT_BUTTON,self.onclear)
self.af = wx.Button(self.panel,label='add additional field')
self.af.Bind(wx.EVT_BUTTON,self.additionalfield)
self.sv = wx.Button(self.panel,label='save')
self.sv.Bind(wx.EVT_BUTTON,self.save)
def showform(self,e):
self.s.SetValue('first name: '+self.f1.GetValue()+'\nlast name: '+self.f2.GetValue()+self.val)
def male(self,e):
self.val=''
self.val = '\ngender: male'
def female(self,e):
self.val=''
self.val='\ngender: female'
def onclear(self,e):
self.s.Clear()
self.f1.Clear()
self.f2.Clear()
def additionalfield(self,e):
self.x = wx.TextCtrl(self.panel,value='\nenter field name: ')
self.x.SetFocus()
self.y = wx.TextCtrl(self.panel,value='enter information ')
self.add = wx.Button(self.panel,label='add')
self.add.Bind(wx.EVT_BUTTON,self.additionalfieldappend)
def additionalfieldappend(self,e):
self.s.AppendText('\n'+self.x.GetValue()+': '+self.y.GetValue())
self.x.Destroy()
self.y.Destroy()
def save(self,e):
if not os.path.exists(self.path):
os.makedirs(self.path)
cnt = open(self.path+'\\'+self.f1.GetValue()+self.f2.GetValue()+'.txt','x')
cnt.write(self.s.GetValue())
nid2obj
app = wx.App()
frame = MyFrame(None,'contact form')
app.MainLoop()
解决方法
每个人在使用wxPython的时候都会发展出自己的风格。正如 Rolf 所建议的,您不仅要向框架添加小部件,还需要添加面板。我在下面添加了一个基本的联系人添加屏幕。 'New' 按钮创建一个 wx.Dialog 的实例,它捕获联系人的详细信息。然后这些可用于 MainFrame,您可以根据需要将它们保存在其中。
请注意,我在应用程序中自由创建了新类来处理不同的关注领域。 GUI 应用可能会变得非常复杂,在我看来,将每一点功能都分解到自己的方法或类中是无可替代的。
并非所有东西都需要成为框架类的成员。
还要注意,我使用了 sizers 而不是绝对位置。
此代码无法完成您想做的所有事情,但可能会帮助您入门。
import wx
BORDER = 5
class MainFrame(wx.Frame):
def __init__(self,*args,**kwargs):
super().__init__(None,**kwargs)
self.size = (400,1000)
self.Title = 'Contacts'
self.Bind(wx.EVT_CLOSE,self.on_quit_click)
self.panel = MainPanel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.panel)
self.SetSizer(sizer)
self.Center()
self.Show()
def new_contact(self,event):
del event
contact_add_screen = NewContact(self)
try:
contact_add_screen.ShowModal()
if contact_add_screen.state == wx.ID_OK:
print(contact_add_screen.first_name)
print(contact_add_screen.last_name)
# This is where you can save your contacts
finally:
contact_add_screen.Destroy()
def on_quit_click(self,event):
del event
wx.CallAfter(self.Destroy)
class MainPanel(wx.Panel):
"""Create a panel class to contain screen widgets."""
def __init__(self,parent,**kwargs):
super().__init__(parent,**kwargs)
self.parent = parent
cmd_new_contact = wx.Button(self,id= wx.ID_NEW)
cmd_new_contact.Bind(wx.EVT_BUTTON,parent.new_contact)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(cmd_new_contact,flag=wx.ALL,border = BORDER)
self.SetSizer(sizer)
class NewContact(wx.Dialog):
def __init__(self,**kwargs)
self.state = None
self.first_name = None
self.last_name = None
self.parent = parent
self.SetTitle('Add Contact')
self.panel = ContactAddPanel(self)
sizer = wx.BoxSizer()
sizer.Add(self.panel)
self.SetSizerAndFit(sizer)
def on_cmd_save_click(self,event):
del event
self.first_name = self.panel.txt_first_name.GetValue()
self.last_name = self.panel.txt_last_name.GetValue()
self.state = wx.ID_OK
self.Destroy()
def on_quit_click(self,event):
del event # unused
self.Destroy()
class ContactAddPanel(wx.Panel):
TEXT_SIZE = (450,-1)
def __init__(self,**kwargs)
self.parent = parent
contact_sizer = self._contact_sizer()
button_panel = ButtonPanel(self,wx.ID_SAVE,self.parent.on_cmd_save_click,self.parent.on_quit_click)
self.txt_first_name.SetFocus()
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(contact_sizer)
sizer.Add(button_panel,flag=wx.EXPAND|wx.TOP,border=BORDER)
main_sizer = wx.BoxSizer(wx.VERTICAL)
main_sizer.Add(sizer,border=BORDER)
self.SetSizer(main_sizer)
def _contact_sizer(self):
lbl_first_name= wx.StaticText(self,label='First name: ')
self.txt_first_name= wx.TextCtrl(self,size=self.TEXT_SIZE)
lbl_last_name = wx.StaticText(self,label='Last name:')
self.txt_last_name = wx.TextCtrl(self,size=self.TEXT_SIZE)
sizer = wx.GridBagSizer(BORDER,BORDER)
sizer.Add(lbl_first_name,pos=(0,0),flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
sizer.Add(self.txt_first_name,1))
sizer.Add(lbl_last_name,pos=(1,flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
sizer.Add(self.txt_last_name,1))
return sizer
class ButtonPanel(wx.Panel):
def __init__(self,ok_id,ok_bind,cancel_bind,**kwargs):
super(ButtonPanel,self).__init__(parent,**kwargs)
self.cmd_action = wx.Button(self,ok_id)
cmd_cancel = wx.Button(self,wx.ID_CANCEL)
self.cmd_action.Bind(wx.EVT_BUTTON,ok_bind)
cmd_cancel.Bind(wx.EVT_BUTTON,cancel_bind)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(self.cmd_action)
sizer.Add((0,proportion=1)
sizer.Add(cmd_cancel)
self.SetSizer(sizer)
if __name__ == '__main__':
wx_app = wx.App()
MainFrame()
wx_app.MainLoop()