python-3.xwxpythonwxtextctrl

How to store an input (TextCtrl) into a variable, process it through some code-lines and show the outputs in another window in wxPython?


I built a script that find a book by pertinence (output) given a quote (input). Now I want to create the GUI of this script and I decided to use wxPython. I would like a basic GUI, where the user can write the phrase in a text bar, then push a button storing the string he entered in a variable. In this way, I can use the variable as input for the algorithm that find the book associated with the entered phrase, showing the title and author as output in a second window.

I built the code that allows me to create the GUI and to store the phrase in the variable var. Now I don't know how to proceed, because I can't access var outside the class. Here the code and the image of the GUI:

class MyFrame(wx.Frame):    
    def __init__(self, *args, **kw):
        super(MyFrame, self).__init__(*args, **kw)
        panel = wx.Panel(self)
        my_sizer = wx.BoxSizer(wx.VERTICAL)

        my_sizer.AddStretchSpacer()

        hbox = wx.BoxSizer(wx.HORIZONTAL)
        manual = wx.StaticText(panel, label='1) Inserisci la citazione --> ')
        font_manual = wx.Font(10, wx.SCRIPT, wx.NORMAL, wx.NORMAL)
        manual.SetFont(font_manual)
        hbox.Add(manual)
        manual2 = wx.StaticText(panel, label='2) Clicca sul logo Bibliovago --> ')
        font_manual2 = wx.Font(10, wx.SCRIPT, wx.NORMAL, wx.NORMAL)
        manual2.SetFont(font_manual2)
        hbox.Add(manual2)
        manual3 = wx.StaticText(panel, label='3) Buona lettura')
        font_manual3 = wx.Font(10, wx.SCRIPT, wx.NORMAL, wx.NORMAL)
        manual3.SetFont(font_manual3)
        hbox.Add(manual3)
        my_sizer.Add(hbox,0, wx.ALIGN_CENTER)

        my_sizer.AddStretchSpacer()

        istr = wx.StaticText(panel, label='Inserisci una citazione')
        font_istr = wx.Font(14, wx.MODERN, wx.NORMAL, wx.NORMAL)
        istr.SetFont(font_istr)
        my_sizer.Add(istr, 0, wx.ALL | wx.CENTER, 5)

        self.text_ctrl = wx.TextCtrl(panel)
        my_sizer.Add(self.text_ctrl, 0, wx.ALL | wx.EXPAND, 5)        

        logo_button = wx.Bitmap('LOGO.png')
        self.my_btn = wx.BitmapButton(panel,-1,logo_button)
        self.Bind(wx.EVT_BUTTON, self.SavePhrase, self.my_btn)
        my_sizer.Add(self.my_btn, 0, wx.ALL | wx.CENTER, 5) 


        panel.SetSizer(my_sizer)

        my_sizer.AddStretchSpacer()

    def SavePhrase(self, event):
        var = self.text_ctrl.GetValue()       

if __name__ == '__main__':
    app = wx.App()
    frm = MyFrame(None, title='BiblioZam', size = (600,400))
    frm.Show()
    app.MainLoop()

GUI image

Should I use my algorithm inside the class as a function? Or there is another way?

Thank you.


Solution

  • When you use classes and you need to access something across methods inside a class, then you need to create the variable by prepending it with self. So in SavePhrase, you need to create var as self.var if other parts of the class need access to it

    If you want to show the results in a separate window, then I would create a new wx.Frame instance inside of SavePhrase and pass it your var. Then you don't need to call it self.var unless something else in MyFrame itself needs to access var.

    Here is an example:

    import wx
    
    class OtherFrame(wx.Frame):
        """
        Class used for creating frames other than the main one
        """
    
        def __init__(self, var, title='Other Frame', parent=None):
            wx.Frame.__init__(self, parent=parent, title=title)
            self.var = var
            print('var = {}'.format(var))
            self.Show()
    
    
    class MyFrame(wx.Frame):
        def __init__(self, *args, **kw):
            super(MyFrame, self).__init__(*args, **kw)
            panel = wx.Panel(self)
            my_sizer = wx.BoxSizer(wx.VERTICAL)
    
            my_sizer.AddStretchSpacer()
    
            hbox = wx.BoxSizer(wx.HORIZONTAL)
            manual = wx.StaticText(panel, label='1) Inserisci la citazione --> ')
            font_manual = wx.Font(10, wx.SCRIPT, wx.NORMAL, wx.NORMAL)
            manual.SetFont(font_manual)
            hbox.Add(manual)
            manual2 = wx.StaticText(panel, label='2) Clicca sul logo Bibliovago --> ')
            font_manual2 = wx.Font(10, wx.SCRIPT, wx.NORMAL, wx.NORMAL)
            manual2.SetFont(font_manual2)
            hbox.Add(manual2)
            manual3 = wx.StaticText(panel, label='3) Buona lettura')
            font_manual3 = wx.Font(10, wx.SCRIPT, wx.NORMAL, wx.NORMAL)
            manual3.SetFont(font_manual3)
            hbox.Add(manual3)
            my_sizer.Add(hbox,0, wx.ALIGN_CENTER)
    
            my_sizer.AddStretchSpacer()
    
            istr = wx.StaticText(panel, label='Inserisci una citazione')
            font_istr = wx.Font(14, wx.MODERN, wx.NORMAL, wx.NORMAL)
            istr.SetFont(font_istr)
            my_sizer.Add(istr, 0, wx.ALL | wx.CENTER, 5)
    
            self.text_ctrl = wx.TextCtrl(panel)
            my_sizer.Add(self.text_ctrl, 0, wx.ALL | wx.EXPAND, 5)
    
            logo_button = wx.Bitmap('LOGO.png')
            self.my_btn = wx.BitmapButton(panel,-1,logo_button)
            self.Bind(wx.EVT_BUTTON, self.SavePhrase, self.my_btn)
            my_sizer.Add(self.my_btn, 0, wx.ALL | wx.CENTER, 5)
    
    
            panel.SetSizer(my_sizer)
    
            my_sizer.AddStretchSpacer()
    
        def SavePhrase(self, event):
            var = self.text_ctrl.GetValue()
            frame = OtherFrame(var=var)
    
    
    if __name__ == '__main__':
        app = wx.App()
        frm = MyFrame(None, title='BiblioZam', size = (600,400))
        frm.Show()
        app.MainLoop()
    

    Now your other frame can use var as needed to generate the result. Note that if generating the result takes a long time, you might want to move that generation step into a thread so it doesn't block your GUI's main loop and cause it to appear to hang.

    You might also find this article of mine helpful - http://www.blog.pythonlibrary.org/2018/10/19/wxpython-how-to-open-a-second-window-frame/