From b935468c9af10445123307d52eaa7f95d7d24b2e Mon Sep 17 00:00:00 2001 From: Paul McCarthy <pauld.mccarthy@gmail.com> Date: Fri, 8 Jan 2016 09:41:44 +0000 Subject: [PATCH] fsl/__init__ now builds GUI interface stuff things on the wx.MainLoop, instead of before the main loop. This is because forcing widget refreshes whilst running off the main loop is more difficult than it should be. --- fsl/__init__.py | 65 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/fsl/__init__.py b/fsl/__init__.py index 9f97f4634..b97174117 100644 --- a/fsl/__init__.py +++ b/fsl/__init__.py @@ -54,8 +54,10 @@ import warnings import os import sys +import time import argparse import importlib +import threading import subprocess @@ -90,25 +92,58 @@ def main(args=None): allTools = _getFSLToolNames() fslTool, args, toolArgs = _parseArgs(args, allTools) + # Is this a GUI tool? if fslTool.interface is not None: - import wx - app = wx.App() - - # Context creation may assume that a wx.App has been created - if fslTool.context is not None: ctx = fslTool.context(toolArgs) - else: ctx = None - - _fslDirWarning(fslTool.toolName, fslEnvActive) - frame = _buildGUI(toolArgs, fslTool, ctx, fslEnvActive) - frame.Show() + import wx - if args.wxinspect: - import wx.lib.inspection - wx.lib.inspection.InspectionTool().Show() - + # The main interface is created on the + # wx.MainLoop, because it is difficult + # to force immediate GUI refreshes when + # not running on the main loop - this + # is important for, e.g. FSLEyes, which + # displays status updates to the user + # while it is loading overlays and + # setting up the interface. + # + # To make this work, this buildGUI + # function is called on a separate thread + # (so it is executed after wx.MainLoop + # has been called), but it schedules its + # work to be done on the wx.MainLoop. + def buildGUI(): + def realBuild(): + + if fslTool.context is not None: ctx = fslTool.context(toolArgs) + else: ctx = None + + _fslDirWarning(fslTool.toolName, fslEnvActive) + + frame = _buildGUI(toolArgs, fslTool, ctx, fslEnvActive) + frame.Show() + + # See comment below + dummyFrame.Destroy() + + if args.wxinspect: + import wx.lib.inspection + wx.lib.inspection.InspectionTool().Show() + + time.sleep(0.1) + wx.CallAfter(realBuild) + + # Create the wx.App object, and create a dummy + # frame. If we don't create a dummy frame, the + # wx.MainLoop call will just return immediately. + # The buildGUI function above will kill the dummy + # frame when it has created the real interface. + app = wx.App() + dummyFrame = wx.Frame(None) + + threading.Thread(target=buildGUI).start() app.MainLoop() - + + # Or is this a CLI tool? elif fslTool.execute is not None: if fslTool.context is not None: ctx = fslTool.context(toolArgs) -- GitLab