使用PySide6/PyQt6实现程序启动画面的处理
<p>在 <strong data-start="140" data-end="159">PySide6 / PyQt6</strong> 或其他 GUI 程序中,启动画面主要有以下几个作用:提升用户体验,当主程序初始化需要几秒钟时,如果界面一直空白,用户可能以为程序没响应;品牌展示,常见做法是在启动画面上放置 公司 Logo、应用图标、版本号、版权信息;程序架构上的过渡,启动画面在主窗口创建前显示,等主程序准备就绪后再关闭,起到 过渡和占位 的作用。</p><h3>1、简单例子代码介绍</h3>
<p>在 <strong data-start="2" data-end="21">PySide6 / PyQt6</strong> 里要实现启动画面(Splash Screen),通常可以用 <strong data-start="52" data-end="69">QSplashScreen</strong> 来完成,和 wx.adv.SplashScreen 类似。它的主要作用是在主窗口加载前,先显示一个过渡画面(通常放 logo、版本号、加载提示)。</p>
<p>简单的案例代码如下所示。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> main():
app </span>=<span style="color: rgba(0, 0, 0, 1)"> QApplication(sys.argv)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 创建启动画面</span>
pixmap = QPixmap(400, 300)<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 可以替换为 QPixmap("logo.png")</span>
pixmap.fill(Qt.white)<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 这里用纯白背景</span>
splash =<span style="color: rgba(0, 0, 0, 1)"> QSplashScreen(pixmap)
splash.showMessage(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">正在加载,请稍候...</span><span style="color: rgba(128, 0, 0, 1)">"</span>, Qt.AlignBottom |<span style="color: rgba(0, 0, 0, 1)"> Qt.AlignCenter, Qt.black)
splash.show()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 模拟加载过程(比如初始化数据库、加载配置等)</span>
<span style="color: rgba(0, 0, 255, 1)">for</span> i <span style="color: rgba(0, 0, 255, 1)">in</span> range(1, 6<span style="color: rgba(0, 0, 0, 1)">):
splash.showMessage(f</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">正在加载资源 {i}/5 ...</span><span style="color: rgba(128, 0, 0, 1)">"</span>, Qt.AlignBottom |<span style="color: rgba(0, 0, 0, 1)"> Qt.AlignCenter, Qt.black)
app.processEvents()</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 让界面刷新</span>
time.sleep(0.5<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 加载完成后进入主窗口</span>
window =<span style="color: rgba(0, 0, 0, 1)"> MainWindow()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 延迟关闭启动画面并显示主窗口</span>
QTimer.singleShot(500, <span style="color: rgba(0, 0, 255, 1)">lambda</span><span style="color: rgba(0, 0, 0, 1)">: (
splash.finish(window),
window.show()
))
sys.exit(app.</span><span style="color: rgba(0, 0, 255, 1)">exec</span><span style="color: rgba(0, 0, 0, 1)">())
</span><span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">:
main()</span></pre>
</div>
<p data-start="1366" data-end="1374"><strong>关键点:</strong></p>
<ol data-start="1375" data-end="1665">
<li data-start="1375" data-end="1540">
<p data-start="1378" data-end="1397"><strong data-start="1378" data-end="1395">QSplashScreen</strong></p>
<ul data-start="1401" data-end="1540">
<li data-start="1401" data-end="1436">
<p data-start="1403" data-end="1436">通过 <code data-start="1406" data-end="1430">QSplashScreen(QPixmap)</code> 创建。</p>
</li>
<li data-start="1440" data-end="1491">
<p data-start="1442" data-end="1491"><code data-start="1442" data-end="1479">showMessage(text, alignment, color)</code> 用来显示提示信息。</p>
</li>
<li data-start="1495" data-end="1540">
<p data-start="1497" data-end="1540"><code data-start="1497" data-end="1513">finish(widget)</code> 在主窗口准备好后关闭 Splash,并显示目标窗口。</p>
</li>
</ul>
</li>
<li data-start="1542" data-end="1606">
<p data-start="1545" data-end="1570"><strong data-start="1545" data-end="1568">app.processEvents()</strong></p>
<ul data-start="1574" data-end="1606">
<li data-start="1574" data-end="1606">
<p data-start="1576" data-end="1606">在耗时操作中调用,确保 Splash 画面能刷新,不会卡死。</p>
</li>
</ul>
</li>
<li data-start="1608" data-end="1665">
<p data-start="1611" data-end="1636"><strong data-start="1611" data-end="1634">QTimer.singleShot()</strong></p>
<ul data-start="1640" data-end="1665">
<li data-start="1640" data-end="1665">
<p data-start="1642" data-end="1665">可以避免界面卡顿,等初始化完成后关闭启动画面。</p>
</li>
</ul>
</li>
</ol>
<h3>2、我使用PySide6/PyQt6实现程序启动画面</h3>
<p>参照上面的过程,我们可以改进下程序启动画面,并结合程序初始化等过程进行展示。</p>
<p>我们在程序登录界面展示,用户确认登录成功后,提示启动画面的。</p>
<p><img src="https://img2024.cnblogs.com/blog/8867/202509/8867-20250914113811255-1479232313.png" alt="image" loading="lazy"></p>
<p> 用户登录成功后,闪屏启动页面进行展示</p>
<p><img src="https://img2024.cnblogs.com/blog/8867/202509/8867-20250914113908541-1030003181.png" alt="image" width="598" height="317" loading="lazy"></p>
<p> 实现过程也是和上面的例子类似,不过增加了一些特殊的处理。</p>
<p>首先封装好显示闪屏界面的函数,如下所示。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)"><strong> show_splash_screen</strong></span>():
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">显示启动闪屏</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(0, 0, 0, 1)">
splash_pix </span>= QPixmap(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">app/images/splash.png</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
splash </span>=<span style="color: rgba(0, 0, 0, 1)"> QSplashScreen(splash_pix, Qt.WindowType.WindowStaysOnTopHint)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 设置字体</span>
font = QFont(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Arial</span><span style="color: rgba(128, 0, 0, 1)">"</span>, 20<span style="color: rgba(0, 0, 0, 1)">, QFont.Weight.Bold)
splash.setFont(font)
splash.showMessage(
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">正在加载,请稍候...</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
Qt.AlignmentFlag.AlignBottom </span>|<span style="color: rgba(0, 0, 0, 1)"> Qt.AlignmentFlag.AlignCenter,
Qt.GlobalColor.yellow,
)
<span style="color: rgba(255, 0, 0, 1)"><strong>splash.show()
</strong></span></span><span style="color: rgba(0, 0, 255, 1)">return</span> splash</pre>
</div>
<p>然后再启动的main.py的main函数中处理各个操作过程即可。</p>
<div class="cnblogs_code">
<pre>async <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"><strong><span style="color: rgba(255, 0, 255, 1)"> init_app</span></strong>():
app </span>=<span style="color: rgba(0, 0, 0, 1)"> SystemApp()
await app.<strong><span style="color: rgba(255, 0, 0, 1)">SetLoginInfo</span></strong>()
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> main():
app </span>=<span style="color: rgba(0, 0, 0, 1)"> QApplication(sys.argv)
event_loop </span>=<span style="color: rgba(0, 0, 0, 1)"> QEventLoop(app)
asyncio.set_event_loop(event_loop)
app_close_event </span>=<span style="color: rgba(0, 0, 0, 1)"> asyncio.Event()
app.aboutToQuit.connect(app_close_event.set)
app.setStyle(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Fusion</span><span style="color: rgba(128, 0, 0, 1)">"</span>)<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 设置样式</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 显示登录窗口</span>
loginDialog =<span style="color: rgba(0, 0, 0, 1)"> FrmLogin()
</span><span style="color: rgba(0, 0, 255, 1)">if</span> loginDialog.<span style="color: rgba(0, 0, 255, 1)">exec</span>() !=<span style="color: rgba(0, 0, 0, 1)"> QDialog.DialogCode.Accepted:
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 如果登录失败或取消,程序退出</span>
<span style="color: rgba(0, 0, 0, 1)"> sys.exit(0)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 显示闪屏</span>
<span style="color: rgba(255, 0, 0, 1)"><strong>splash = show_splash_screen()
</strong></span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 主窗口</span>
main_window =<span style="color: rgba(0, 0, 0, 1)"> MainWindow()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 设置托盘图标</span>
<span style="color: rgba(0, 0, 0, 1)"> setup_tray_icon(app, main_window)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 闪屏后显示主界面, 1秒后窗口最大化显示</span>
<span style="color: rgba(255, 0, 0, 1)"><strong> QTimer.singleShot(1000, lambda: (splash.close(), main_window.showMaximized()))
</strong></span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> sys.exit(app.exec())</span>
<span style="color: rgba(0, 0, 0, 1)">
with event_loop:
event_loop.create_task(<span style="color: rgba(255, 0, 0, 1)"><strong>init_app()</strong></span>)
event_loop.run_until_complete(app_close_event.wait())
</span><span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">:
main()</span></pre>
</div>
<p>我们的主程序使用了异步的操作,因此和上面的例子有所差异,在用户登录成功后,前端会获得相关的用户身份信息,并在<strong><span style="color: rgba(255, 0, 0, 1)"> init_app()</span></strong> 函数中进行用户身份信息的获取和设置。</p>
<p>我们把用户身份信息的处理,单独抽取出来,放在system_app类里面进行处理,如下所示,可以根据登录用户的信息,获取用户的当前拥有的功能权限,角色集合等等。</p>
<p><img src="https://img2024.cnblogs.com/blog/8867/202509/8867-20250914114849017-1264603685.png" alt="image" width="951" height="1227" loading="lazy"></p>
<p>前面随笔我介绍过, 对于列表和对话框界面的封装,能够简化对泛型模型数据的统一处理,通用对于前端用户身份信息,我们也可以集中在基类中获取。</p>
<p><img src="https://img2024.cnblogs.com/blog/8867/202502/8867-20250226144241472-1488282641.png" alt="" class="medium-zoom-image" loading="lazy"></p>
<p><img src="https://img2024.cnblogs.com/blog/8867/202509/8867-20250914115427349-1192132373.png" alt="image" width="797" height="438" loading="lazy"></p>
<p> 编辑对话框的基类同样的处理。</p>
<p><img src="https://img2024.cnblogs.com/blog/8867/202509/8867-20250914115546823-1829558458.png" alt="image" width="795" height="751" loading="lazy"></p>
<p> 这样我们在用户前端界面中,需要设置用户当前信息的时候,就可以随时通过基类函数进行获取了。</p>
<p>上面代码,结合闪屏启动界面的处理过程,介绍了在用户登录成功后,对用户相关信息的处理过程。</p>
</div>
<div id="MySignature" role="contentinfo">
<div style="border-right-color: #cccccc; border-right-width: 1px; border-right-style: solid; padding-right: 5px; border-top-color: #cccccc; border-top-width: 1px; border-top-style: solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left-color: #cccccc; border-left-width: 1px; border-left-style: solid; width: 98%; padding-top: 4px; border-bottom-color: #cccccc; border-bottom-width: 1px; border-bottom-style: solid; background-color: #eeeeee;">
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" alt>
<span style="color: #000000"><span class="Apple-tab-span" style="white-space: pre"></span>
专注于代码生成工具、.Net/Python 框架架构及软件开发,以及各种Vue.js的前端技术应用。著有Winform开发框架/混合式开发框架、微信开发框架、Bootstrap开发框架、ABP开发框架、SqlSugar开发框架、Python开发框架等框架产品。
<br> 转载请注明出处:撰写人:伍华聪 http://www.iqidi.com <br> </span></div><br><br>
来源:https://www.cnblogs.com/wuhuacong/p/19091163
頁:
[1]