write contact form in wxPython?

Viewed 74

I have a code. When it runs, you click on add contact button and add some contact. When you press on each contact, it just shows you the last contact information you have added. But when I press on each contact, I want it to instead show me the information for the contact I have clicked. Who can help me to solve this problem?

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, parent, 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', pos=(0,50))

        self.rbm = wx.RadioButton(self.panel, label='male', style=RB_GROUP, pos=(0,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', pos=(0,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()
1 Answers

Everyone will develop their own style when using wxPython. As Rolf has suggested, you do not just add widgets to a frame, but you need to add a panel. I have added a basic contact add screen below. The 'New' button creates an instance of a wx.Dialog, which captures the details of a contact. These are then available to the MainFrame where you can save them if you want.

Note that I have freely created new classes in the application to handle the different areas of concern. GUI apps can become very complex, and in my opinion, there is no substitute for factoring each bit of functionality into its own method or class.

Not everything needs to be a member of the frame class.

Note also the I have used sizers and not absolute positions.

This code does not do everything that you want to do, but it might help get you started.

import wx

BORDER = 5

class MainFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(None, *args, **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, *args, **kwargs):
        super().__init__(parent, *args, **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, parent, *args, **kwargs):
        super().__init__(parent, *args, **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, parent, *args, **kwargs):
        super().__init__(parent, *args, **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, flag=wx.ALL, 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, pos=(0, 1))
        sizer.Add(lbl_last_name, pos=(1, 0), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
        sizer.Add(self.txt_last_name, pos=(1, 1))
        return sizer


class ButtonPanel(wx.Panel):
    def __init__(self, parent, ok_id, ok_bind, cancel_bind, *args, **kwargs):
        super(ButtonPanel, self).__init__(parent, *args, **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, 0), proportion=1)
        sizer.Add(cmd_cancel)
        self.SetSizer(sizer)

if __name__ == '__main__':
        wx_app = wx.App()
        MainFrame()
        wx_app.MainLoop()
Related