How to make GUI draw - before time consuming call?

I’m fooling around with wxPython, 1’st time – and have a question…

I’ve used Glade to set up (draw) a GUI as I want it. I’m now in a
phase of adding functionality.
Basically the program should read the win-log files and quickly list
when I have logged in and out the last weeks (months), so I can get
easily around time registration at work. All the log file reading is
handled by a sub-program “nTidCore”, that is not part of this
question.

My problem right now is essentially a question of timing in drawing
the GUI. The GUI is good looking as it is, but I need to call a sub-
routine “FillText” to populate various fields. This subroutine has to
read through all the logs, and do potentially take like 10 seconds. I
would like the GUI to get fully drawn to the screen, before calling
the sub routine, so that the user can look at a nice GUI, maybe saying
“Please wait a moment”, while it reads through.

Where, in the code, do I put the call that populates my variables, so
that the GUI will draw first, before this time consuming call?

I include my code, in case it can help you answer my question.

Thanks in advance… Martin

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

import wx
import nTidCore

class nTidGUI(wx.Frame):
    def __init__(self, *args, **kwds):
        # begin wxGlade: nTidGUI.__init__
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.panel_Main = wx.Panel(self, -1)

        # Menu Bar
        self.frame_Main_menubar = wx.MenuBar()
        wxglade_tmp_menu = wx.Menu()
        itmExit = wxglade_tmp_menu.Append(wx.ID_EXIT, "Quit", "Exit
the application...", wx.ITEM_NORMAL)
        self.frame_Main_menubar.Append(wxglade_tmp_menu, "File")
        wxglade_tmp_menu = wx.Menu()
        itmAbout = wxglade_tmp_menu.Append(wx.ID_ABOUT, "About",
"About the application...", wx.ITEM_NORMAL)
        self.frame_Main_menubar.Append(wxglade_tmp_menu, "Help")
        self.SetMenuBar(self.frame_Main_menubar)
        # Menu Bar end
        self.frame_Main_statusbar = self.CreateStatusBar(2, 0)
        self.label_User = wx.StaticText(self.panel_Main, -1, "User")
        self.label_Mode = wx.StaticText(self.panel_Main, -1, "Mode")
        self.combo_box_User = wx.ComboBox(self.panel_Main, -1,
choices=nTidCore.ListUsers(), style=wx.CB_DROPDOWN)
        self.combo_box_Mode = wx.ComboBox(self.panel_Main, -1,
choices=nTidCore.ListModes(), style=wx.CB_DROPDOWN)
        self.button_DefUser = wx.Button(self.panel_Main, -1,
"Default")
        self.button_DefMode = wx.Button(self.panel_Main, -1,
"Default")
        self.radio_box_Time = wx.RadioBox(self.panel_Main, -1, "Time
interval", choices=["This week", "Last week", "This week + last week",
"This month", "Last month", "Everything ..."], majorDimension=3,
style=wx.RA_SPECIFY_ROWS)
        self.text_ctrl_Output = wx.TextCtrl(self.panel_Main, -1, "",
style=wx.TE_MULTILINE)
        self.button_Quit = wx.Button(self.panel_Main, -1, "Quit")

        self.__set_properties()
        self.__do_layout()
        # end wxGlade

        # Bindings
        self.Bind(wx.EVT_MENU, self.OnAbout, itmAbout)
        self.Bind(wx.EVT_MENU, self.OnExit, itmExit)
        self.Bind(wx.EVT_BUTTON, self.OnExit, self.button_Quit)
        # Some events on ComboBox changes and DefaultKey press ...

    def __set_properties(self):
        # begin wxGlade: nTidGUI.__set_properties
        self.SetTitle("nTid")
        self.frame_Main_statusbar.SetStatusWidths([-1, 0])
        # statusbar fields
        frame_Main_statusbar_fields = ["mTid, In No time ...",
"Reading information from computers log file(s)..."]
        for i in range(len(frame_Main_statusbar_fields)):

self.frame_Main_statusbar.SetStatusText(frame_Main_statusbar_fields[i],
i)
        self.radio_box_Time.SetSelection(2)
        self.text_ctrl_Output.SetMinSize((400, 256))
        self.button_Quit.SetToolTipString("Press here when you are
done...")
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: nTidGUI.__do_layout
        sizer_Main = wx.BoxSizer(wx.HORIZONTAL)
        sizer_MajorControls = wx.BoxSizer(wx.VERTICAL)
        sizer_Controls = wx.BoxSizer(wx.VERTICAL)
        sizer_Selectors = wx.BoxSizer(wx.HORIZONTAL)
        sizer_2 = wx.BoxSizer(wx.VERTICAL)
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_Lables = wx.BoxSizer(wx.VERTICAL)
        sizer_Lables.Add(self.label_User, 1, wx.ALL|
wx.ALIGN_CENTER_VERTICAL, 6)
        sizer_Lables.Add(self.label_Mode, 1, wx.ALL|
wx.ALIGN_CENTER_VERTICAL, 6)
        sizer_Selectors.Add(sizer_Lables, 0, wx.EXPAND, 0)
        sizer_1.Add(self.combo_box_User, 1, wx.ALL|wx.EXPAND, 4)
        sizer_1.Add(self.combo_box_Mode, 1, wx.ALL|wx.EXPAND, 4)
        sizer_Selectors.Add(sizer_1, 1, wx.EXPAND, 0)
        sizer_2.Add(self.button_DefUser, 0, wx.ALL, 4)
        sizer_2.Add(self.button_DefMode, 0, wx.ALL, 4)
        sizer_Selectors.Add(sizer_2, 0, wx.EXPAND, 0)
        sizer_Controls.Add(sizer_Selectors, 0, wx.EXPAND, 0)
        sizer_Controls.Add(self.radio_box_Time, 0, wx.ALL|wx.EXPAND,
4)
        sizer_MajorControls.Add(sizer_Controls, 0, wx.EXPAND, 0)
        sizer_MajorControls.Add(self.text_ctrl_Output, 1, wx.ALL|
wx.EXPAND, 4)
        sizer_MajorControls.Add(self.button_Quit, 0, wx.ALL|
wx.ALIGN_CENTER_HORIZONTAL, 4)
        self.panel_Main.SetSizer(sizer_MajorControls)
        sizer_Main.Add(self.panel_Main, 1, wx.EXPAND, 0)
        self.SetSizer(sizer_Main)
        sizer_Main.Fit(self)
        self.Layout()
        # end wxGlade

    def FillText(self):
        self.text_ctrl_Output.Clear()
        lstDefault = nTidCore.ReadLog("winXPlog")[1]
        for line in lstDefault:
            self.text_ctrl_Output.AppendText("\n"+str(line))

    def OnAbout(self,e):
        # A message dialog box with an OK button. wx.OK is a standard
ID in wxWidgets.
        dlg = wx.MessageDialog( self, "A small application", "About
nTid", wx.OK)
        dlg.ShowModal() # Show it
        dlg.Destroy() # finally destroy it when finished.

    def OnExit(self,e):
        self.Close(True) # Close the frame.

# end of class nTidGUI

if __name__ == "__main__":
    app = wx.PySimpleApp(0)
    wx.InitAllImageHandlers()
    frame_Main = nTidGUI(None, -1, "")
    app.SetTopWindow(frame_Main)
    frame_Main.Show()
    app.MainLoop()

In case you need/want to run the program please use the following as nTidCore.py

#!/usr/bin/python

def ListUsers():
return [“Abcde”,“Fghij”,“Klmno”]

def ListModes():
return [“Login/Logout”,“SequrityLog”,“Everything”]

if name == ‘main’:
print(" ! This is not a Main program, please don’t call it directly…")

Simply initialise text_ctrl_Output to something like "Getting Data
Please Wait", in FillText get your data before clearing the text control
and at the end of __init__ use wx.CallAfter(FillText) to populate your
default list after the GUI is drawn. You might also like to consider
keeping the data, i.e. assigning it to self.DataList or some such then
you will not need to reread all the files on each display filter change.

Gadget/Steve

···

On 28/12/2011 7:14 PM, MartinHvidberg wrote:

I�m fooling around with wxPython, 1�st time � and have a question�

I�ve used Glade to set up (draw) a GUI as I want it. I�m now in a
phase of adding functionality.
Basically the program should read the win-log files and quickly list
when I have logged in and out the last weeks (months), so I can get
easily around time registration at work. All the log file reading is
handled by a sub-program �nTidCore�, that is not part of this
question.

My problem right now is essentially a question of timing in drawing
the GUI. The GUI is good looking as it is, but I need to call a sub-
routine �FillText� to populate various fields. This subroutine has to
read through all the logs, and do potentially take like 10 seconds. I
would like the GUI to get fully drawn to the screen, before calling
the sub routine, so that the user can look at a nice GUI, maybe saying
�Please wait a moment�, while it reads through.

Where, in the code, do I put the call that populates my variables, so
that the GUI will draw first, before this time consuming call?

I include my code, in case it can help you answer my question.

Thanks in advance� Martin

Thanks. “wx.CallAfter(FillText)” was just what I needed… :slight_smile: Martin

No Problem!

Gadget/Steve

···

On 29/12/2011 7:43 PM, Martin Hvidberg wrote:

Thanks. "wx.CallAfter(FillText)" was just what I needed... :slight_smile: Martin
--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en