我正在运行一个wxPython应用程序,它在开始时导入很多模块和包,并收集有关计算机的信息(网络接口,互联网连接......)所以需要时间,我正在显示徽标在那个时间直到它结束。问题是,如果你按下徽标就会崩溃(因为导入是在MainThread上而GUI不能响应事件),如何在导入时显示徽标而不会让GUI崩溃? (我不想让用户点击徽标)
答案 0 :(得分:0)
在最近的项目中(在Windows7和wxPython 2.9.5.1上):为了在模块导入时显示wx.SplashScreen
,我们执行了以下操作:
我们有一个主模块,它在开头import wx
创建wx.App
并显示启动画面。只有在显示启动画面后,我们才开始导入“重型”模块。第一次启动需要40秒。事实上,如果用户点击启动画面,应用程序将崩溃。更好的是,Windows显示一个消息框( EDIT2 ),“Python.exe已停止工作”。如果用户点击“终止”,该应用程序实际上将终止/崩溃。如果用户什么都不做,应用程序将正常启动。所以在Windows上没有“真正的”崩溃。第二次启动时也不会发生这种情况(因为事情是缓存的)?在后续启动时,启动时间为5秒。对不起,没有真正的答案,但评论也太长了。
编辑:添加了最低工作示例:在显示时,每次在启动时点击一两秒,以使Windows显示“Python已停止工作”对话框。 <{1}}返回后,对话框就会消失。
long_running()
答案 1 :(得分:0)
受到Tim Roberts的启发wxPython-users thread我首先试图在一个单独的线程中剥离启动画面,但这不起作用(wxwidgets抱怨它不在主线程中)。所以我做了我应该首先做的唯一显而易见的事情:在启动时长时间运行一个单独的线程。
副作用:由于启动画面现在可以对事件做出反应,因此点击时它会消失。
import wx
class long_running(object):
def __init__(self):
bitmap = wx.EmptyBitmap(300, 150, 127)
self.mainframe = wx.Frame(None, -1, 'mainframe')
self.splash = wx.SplashScreen(bitmap, wx.SPLASH_TIMEOUT, 20000, self.mainframe)
def start(self):
import time
# mimicking something taking very long time on startup
for i in range(20):
time.sleep(0.5)
print i
wx.CallAfter(self.continue_)
def continue_(self):
#Destroy the splash screen.
if self.splash:
self.splash.Hide()
# self.splash.Destroy()
self.mainframe.Show()
if __name__ == '__main__':
import thread
app = wx.App()
long_rnn = long_running()
# Begin loading the application.
thread.start_new_thread(long_rnn.start, ())
# Application loaded.
app.MainLoop()