GUI经典实践-网速测试小工具-2

2022-06-17 09:07:36 浏览数 (1)

未响应是为什么?

当我们的代码在后台运行的时候,CPU 会被抢占,此时我们的窗口将会停止刷新从而呈现未响应状态,操作系统认为我们程序已经停止。但是如果我们程序就需要耗费一些时间,怎么办呢?官方文档建议我们占用一个主线程来守护程序,具体就是让我们的 GUI 程序成为一个单独的线程,这样 GUI 就能持续占用 CPU ,这个问题也就迎刃而解。

如何做呢?

接上篇文章,我们计划将测速的步骤写成独立的方法,同时在主方法 start 中调用他们,然后在 GUI 的事件循环中起一个线程(将这个线程设置为守护线程)来执行主方法 start,这样我们的未响应和实时刷新功能都可以解决。

代码

代码语言:javascript复制
# -*- coding: utf-8 -*-
import PySimpleGUI as sg
from speedtest_cli import Speedtest
import threading

# 实例化测速对象
spt = Speedtest()

# 设置主题
sg.theme('BlueMono')

# 布局元素
one_line = [sg.Text('最佳服务器:'),sg.Text(size=(50,1),key='-BSTS-')]
two_line = [sg.Text('下载速度:'),sg.Text(size=(50,1),key='-DLS-')]
three_line = [sg.Text('上传速度:'),sg.Text(size=(50,1),key='-UPS-')]
four_line = [sg.Button('开始测试'),sg.Button('退出')]
five_line = [sg.Text(size=(50,1),key='-INFO-')]

# 布局
layout = [
    one_line,
    two_line,
    three_line,
    four_line,
    five_line
]

def get_best_server(window):
    window['-INFO-'].update('开始获取服务器...',text_color='red')
    res = spt.best.get('sponsor')
    print(res)
    window['-BSTS-'].update(res,text_color='yellow')

def get_download_speed(window):
    window['-INFO-'].update('开始获测试下载速率...',text_color='red')
    dSp1=spt.download()
    dSp=f'{dSp1/1024/1024:.2f} Mb/s'
    window['-DLS-'].update(dSp,text_color='yellow')

def get_upload_speed(window):
    window['-INFO-'].update('开始获测试上传速率...',text_color='red')
    uSp1=spt.upload()
    uSp=f'{uSp1/1024/1024:.2f} Mb/s'
    window['-UPS-'].update(uSp,text_color='yellow')

def end(window):
    window['-INFO-'].update('测试完成...',text_color='red')

def start(window):
    get_best_server(window)
    get_download_speed(window)
    get_upload_speed(window)
    end()

# 创建窗口
window = sg.Window('网速测试小工具', layout)

# 事件循环 event loop
while True:

    event, values = window.read(timeout=100)
    if event in (sg.WIN_CLOSED, '退出'):
        # 用户关闭窗口或者点击退出后退出
        break

    if event == '开始测试':
        # 解决由于代码执行耗时而导致窗口未响应的问题,使用threading(守护模式)解决
        t1 = threading.Thread(target=start,daemon=True,args=[window])
        t1.start()

        print(f'Event: {event}')
        print(str(values))

window.close()

效果

至此,问题完美解决~

Tip

  • 主题要在布局前就设置
  • 使用守护线程解决未响应的问题
  • 业务逻辑在主方法中就完成编排

以上就是今天的全部内容了,感谢您的阅读,我们下节再会。

gui

0 人点赞