使用 PyQt5 启动画面覆盖模块加载时间
Using PyQt5 splash screen to cover module load time
我创建了一个 GUI 来加载依赖于大量模块的库 my_lib
。它将使用 PyInstaller 转换为可执行文件。
我想创建启动画面来隐藏较长(超过 5 秒)的加载时间。
一种方法是使用 PyInstaller 的 --splash
参数,但这将独立于程序并使用计时器工作。
另一种方法是。这是主要脚本的示例:
# various imports including standard library and PyQt.
from my_lib import foo, bar, docs_url, repo_url
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.action_docs.triggered.connect(lambda x: QDesktopServices.openUrl(QUrl(docs_url)))
self.action_code.triggered.connect(lambda x: QDesktopServices.openUrl(QUrl(repo_url)))
def show_splash(self):
self.splash = QSplashScreen(QPixmap("path\to\splash.png"))
self.splash.show()
# Simple timer to be replaced with better logic.
QTimer.singleShot(2000, self.splash.close)
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyle(QStyleFactory.create('fusion'))
main = MainWindow()
main.show()
main.show_splash()
sys.exit(app.exec_())
上面代码的问题在于导入是在顶部完成的然后启动画面被打开,这就违背了这一点。
此外,MainWindow
class 的定义取决于从 my_lib
.
导入的对象
当GUI的基本定义依赖它们时,如何隐藏重型模块的加载时间?
我有什么遗漏吗?有可能吗?
编辑:这种做法是不必要的。正如@musicamante 在评论中指出的那样,上面的(编辑过的)示例没有引发任何错误,可以毫无问题地使用。
在考虑了@musicamante 的评论后,我有了将 __ main __ 条件中的逻辑分成两部分的想法。一个在大量进口之前,另一个在最后。所以它是这样的:
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyle(QStyleFactory.create('fusion'))
splash_object = QSplashScreen(QPixmap("path\to\splash.png"))
splash_object.show()
#
# Load the heavy libraries, including my_lib.
#
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
if __name__ == '__main__':
splash_object.close()
main = MainWindow()
main.show()
sys.exit(app.exec_())
这似乎工作得很好,但我不确定这种拆分是否有任何副作用。
应该注意的是,大部分启动时间似乎来自可执行文件的解包。
编辑:This answer 建议采用类似的方法。
我创建了一个 GUI 来加载依赖于大量模块的库 my_lib
。它将使用 PyInstaller 转换为可执行文件。
我想创建启动画面来隐藏较长(超过 5 秒)的加载时间。
一种方法是使用 PyInstaller 的 --splash
参数,但这将独立于程序并使用计时器工作。
另一种方法是
# various imports including standard library and PyQt.
from my_lib import foo, bar, docs_url, repo_url
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.action_docs.triggered.connect(lambda x: QDesktopServices.openUrl(QUrl(docs_url)))
self.action_code.triggered.connect(lambda x: QDesktopServices.openUrl(QUrl(repo_url)))
def show_splash(self):
self.splash = QSplashScreen(QPixmap("path\to\splash.png"))
self.splash.show()
# Simple timer to be replaced with better logic.
QTimer.singleShot(2000, self.splash.close)
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyle(QStyleFactory.create('fusion'))
main = MainWindow()
main.show()
main.show_splash()
sys.exit(app.exec_())
上面代码的问题在于导入是在顶部完成的然后启动画面被打开,这就违背了这一点。
此外,MainWindow
class 的定义取决于从 my_lib
.
当GUI的基本定义依赖它们时,如何隐藏重型模块的加载时间? 我有什么遗漏吗?有可能吗?
编辑:这种做法是不必要的。正如@musicamante 在评论中指出的那样,上面的(编辑过的)示例没有引发任何错误,可以毫无问题地使用。
在考虑了@musicamante 的评论后,我有了将 __ main __ 条件中的逻辑分成两部分的想法。一个在大量进口之前,另一个在最后。所以它是这样的:
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyle(QStyleFactory.create('fusion'))
splash_object = QSplashScreen(QPixmap("path\to\splash.png"))
splash_object.show()
#
# Load the heavy libraries, including my_lib.
#
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
if __name__ == '__main__':
splash_object.close()
main = MainWindow()
main.show()
sys.exit(app.exec_())
这似乎工作得很好,但我不确定这种拆分是否有任何副作用。
应该注意的是,大部分启动时间似乎来自可执行文件的解包。
编辑:This answer 建议采用类似的方法。