I\'m building an application with wxPython and a Deep Learning model that I created using Tensorflow. The design pattern that I\'m using is MVC. My problem is that the deep
You could use the _thread
module and the PyPubSub
module to keep the main thread completely functional during the loading of the model.
However, keep in mind that if you have a wx.Button
in the GUI bound to method A
and method A
requires the full model to be loaded to properly run, then users will be able to click the wx.Button
and the program will probably hang because the model is still not fully loaded. If this is the case, you could use the methods Disable()
(while the model is being loaded) and Enable()
(after the model is loaded) to prevent this.
Code with comments (####).
import wx
import time
import _thread
from pubsub import pub
class Model:
def __init__(self):
'''This part is simulating the loading of tensorflow'''
x = 0
while x < 15:
time.sleep(1)
print(x)
#### This is how you broadcast the 'Loading' message
#### from a different thread.
wx.CallAfter(pub.sendMessage, 'Loading', x=x)
x += 1
#### The same as before
wx.CallAfter(pub.sendMessage, 'Loading', x=x)
class View(wx.Frame):
def __init__(self, parent, title):
super(View, self).__init__(parent, title=title, size=(400, 400))
self.InitUI()
def InitUI(self):
# Defines the GUI controls
#### It needed to set the size of the panel to cover the frame
#### because it was not covering the entire frame before
masterPanel = wx.Panel(self, size=(400, 400))
masterPanel.SetBackgroundColour("gold")
self.vbox = wx.BoxSizer(wx.VERTICAL)
self.fgs = wx.FlexGridSizer(6, 2, 10, 25)
id = wx.StaticText(self, label="ID:")
firstName = wx.StaticText(self, label="First name:")
lastName = wx.StaticText(self, label="Last name:")
self.idTc = wx.TextCtrl(self)
self.firstNameTc = wx.TextCtrl(self)
self.lastNameTc = wx.TextCtrl(self)
self.fgs.AddMany([id, (self.idTc, 1, wx.EXPAND),
firstName, (self.firstNameTc, 1, wx.EXPAND),
lastName, (self.lastNameTc, 1, wx.EXPAND)])
self.vbox.Add(self.fgs, proportion=1, flag=wx.ALL | wx.EXPAND,
border=15)
self.SetSizer(self.vbox)
self.vbox.Fit(self)
self.Layout()
#### Create status bar to show loading progress.
self.statusbar = self.CreateStatusBar(1)
self.statusbar.SetStatusText('Loading model')
#### Set the size of the window because the status bar steals space
#### in the height direction.
self.SetSize(wx.DefaultCoord, 160)
#### Subscribe the class to the message 'Loading'. This means that every
#### time the meassage 'Loading' is broadcast the method
#### ShowLoadProgress will be executed.
pub.subscribe(self.ShowLoadProgress, 'Loading')
#### Start the thread that will load the model
_thread.start_new_thread(self.LoadModel, ('test',))
def LoadModel(self, test):
"""
Load the Model
"""
#### Change depending on how exactly are you going to create/load the
#### model
self.model = Model()
def ShowLoadProgress(self, x):
"""
Show the loading progress
"""
if x < 15:
self.statusbar.SetStatusText('Loading progress: ' + str(x))
else:
self.statusbar.SetStatusText('All loaded')
class Controller:
def __init__(self):
self.view = View(None, title='Test')
self.view.Show()
#### The line below is not needed now because the model is
#### loaded now from the thread started in View.InitUI
#self.model = Model()
def main():
app = wx.App()
controller = Controller()
app.MainLoop()
if __name__ == '__main__':
main()
If you load the model from a method inside class View
then you will not need the PyPubSub module because you could just call wx.CallAfter(self.ShowLoadProgress, x)