Search code examples
pythonwxpythonpanels

On click button, data from panel two field should be copied to panel one field?


I am a beginner in python language and I am trying to make a simple gui for my program using wxpython. My gui consists of a frame and two tabs (using wxPanel) on it (tab 1 and tab 2). I placed txtctrl widgets on both tab 1 and tab 2. On tab 1 , I placed a button which gets all txtctrl values and assigns them to corresponding variables. My problem is that, I can get the values from txtctrls which are placed in tab 1 panel and assign them to variables in tab 1, but I can not get values from txtctrls which are in tab 2 panel and use them in tab 1 panel (I want to get values from tab 2 panel and assign them to variables in tab 1 panel.). Could you please help me to solve this problem and run my code.

I searched many sites, read examples on data transfer between frames or classes, and tried to apply them, however still I couldn' t make it work.

here is my gui code;

from wxPython.wx import *
import os

class PageOne(wxPanel):
    def __init__(self, parent):
        wxPanel.__init__(self, parent)
        self.SetBackgroundColour("gray")

        self.tc1=wxTextCtrl(self, -1, '',  (110, 15), (120, -1))
        self.tc2=wxTextCtrl(self, -1, '',  (110, 15), (120, -1))
        self.tc3=wxTextCtrl(self, -1, '',  (110, 15), (120, -1))
        self.st1=wxStaticText(self, -1, "input", pos=(10, 12))
        self.st2=wxStaticText(self, -1, "X:", pos=(10, 12))
        self.st3=wxStaticText(self, -1, "Y:", pos=(10, 12))
        self.st4=wxStaticText(self, -1, "Z:", pos=(10, 12))
        #flexgrid 
        self.fgs = wxFlexGridSizer(1, 7, 9, 10) 
        self.fgs.AddMany([(self.st1, 1, wxEXPAND),(self.st2, 1, \
        wxEXPAND),(self.tc1, 1,wxEXPAND),(self.st3, 1, wxEXPAND),\
        (self.tc2, 1, wxEXPAND),(self.st4, 1, wxEXPAND),(self.tc3, 1,\
        wxEXPAND)])
        # statik text 
        self.hsizer1 = wxBoxSizer(wxHORIZONTAL)
        self.hsizer2 = wxBoxSizer(wxHORIZONTAL)
        self.vsizerb = wxBoxSizer(wxVERTICAL)

        self.hsizer1.Add(self.fgs, 1, wxEXPAND |wxALIGN_CENTER| wxALL,1)

        self.but1=wxButton(self, 1, 'Calculate', (10, 10))
        self.but1.Bind(EVT_BUTTON, self.Create_OnClick)
        self.hsizer2.Add(self.but1, 1, wxALIGN_CENTER)

        self.vsizerb.Add(self.hsizer1, 1.8, wxEXPAND | wxALL, 10)
        self.vsizerb.Add(self.hsizer2, 0.2, wxEXPAND | wxALL, 10)
        self.SetSizer(self.vsizerb)

        self.PTWO=PageTwo(self)
        self.PTWO.Show()

    def Create_OnClick(self, event):
        text1=self.tc1.GetValue()
        text2=self.tc2.GetValue()
        text3=self.tc3.GetValue()
        #here I want to get pt2_1 value from tab2 panel and assign it
        #to text4 varibale.
        #on the gui, if you fill all txtcrtl boxes and press calculate 
        #button, it gives values of text3 and text4 on cmd.
        #I can get text3 value but cannot get text4 value.It gives null?
        text4=self.PTWO.pt2_1.GetValue()
        print "text_fromtab2:",text4,"text_fromtab1:",text3
        yer=os.getcwd()

class PageTwo(wxPanel):
    def __init__(self, parent):
        wxPanel.__init__(self, parent)
        self.SetBackgroundColour("gray")

        self.hsizerb = wxBoxSizer(wxHORIZONTAL)
        self.st5=wxStaticText(self, -1, "Input 1 (mm)", pos=(10, 12))
        # I want to be able to get these values from PageOne 
        self.pt2_1=wxTextCtrl(self, -1, '',  (110, 15), (120, -1))

        self.fgs_pt2 = wxFlexGridSizer(1, 2, 10, 10)   
        self.fgs_pt2.AddMany([(self.st5, 1, wxEXPAND),(self.pt2_1, 1,\
        wxEXPAND)])
        self.hsizerb.Add(self.fgs_pt2, 1, wxEXPAND |wxALIGN_CENTER| \
        wxALL, 10)
        self.SetSizer(self.hsizerb)

class MainFrame(wxFrame):
    def __init__(self, parent, fid, title):
        wxFrame.__init__(self, parent, fid, title, \
            pos = (200, 50), \
            size = (500, 200), \
            style = wxDEFAULT_FRAME_STYLE \
                |wxNO_FULL_REPAINT_ON_RESIZE)

        panel1 = wxPanel(self, -1)
        panel1.SetBackgroundColour("blue")

        nb = wxNotebook(panel1)
        page1 = PageOne(nb)
        page2 = PageTwo(nb)

        nb.AddPage(page1, "Tab 1")
        nb.AddPage(page2, "Tab 2")

        sizer = wxBoxSizer(wxVERTICAL)
        sizer.Add(nb, 1, wxALL|wxALIGN_CENTER|wxEXPAND, 1 )
        panel1.SetSizer(sizer)
        panel1.SetAutoLayout(True)
        self.Show(True)

if __name__ == "__main__":
        app = wxPySimpleApp()
        frame = MainFrame(None, wxID_ANY, "MY PROGRAM")
        app.MainLoop()

Solution

  • You are creating PageTwo twice, when you have already created it in MainFrame

    nb = wxNotebook(panel1)
    page1 = PageOne(nb)
    page2 = PageTwo(nb)
    
    nb.AddPage(page1, "Tab 1")
    nb.AddPage(page2, "Tab 2")
    

    you don't need to recreate it in PageOne, so remove this

    self.PTWO=PageTwo(self)
    self.PTWO.Show()
    

    Instead pass PageTwo to PageOne e.g.

    class PageOne(wxPanel):
        def __init__(self, parent, page2):
            wxPanel.__init__(self, parent)
            self.PTWO=page2
    

    and in MainFrame

    nb = wxNotebook(panel1)
    page2 = PageTwo(nb)
    page1 = PageOne(nb, page2)
    

    Once you have done these changes you should be able to access values from page2 correctly, but that said you need to think more about what are you trying to do?

    • Better way would be to let pages save values to some model/object and other pages can access that data instead of directly accessing UI elements, because you may need to show error and clean data before processing anyway, you can do that on tab change

    • Have better variable names instead of text1 use self.textX or self.X etc

    • You should separate out calculation function to a third class or may be Mainframe, page1 and page2 should only collect data