import PySimpleGUI as sg
import math
import time
from threading import Event
def calculate_sqrt_sum(window, stop_event):
    """
    后台计算函数:计算1亿以内自然数的平方根之和
    """
    total = 100_000_000
    batch_size = 1_000_000
    sum_result = 0.0
    start_time = time.time()
    try:
        for i in range(1, total + 1):
            sum_result += math.sqrt(i)
            # 进度更新
            if i % batch_size == 0 or i == total:
                progress = i / total * 100
                elapsed = time.time() - start_time
                # 发送进度更新事件(使用元组传递多个值)
                window.write_event_value('-PROGRESS-', (
                    f'已处理 {i:,} 个数...',
                    progress,
                    sum_result,
                    elapsed
                ))
                # 检查停止信号
                if stop_event.is_set():
                    window.write_event_value('-CANCELED-', None)
                    return
        # 计算完成
        elapsed = time.time() - start_time
        window.write_event_value('-DONE-', (sum_result, elapsed))
    except Exception as e:
        window.write_event_value('-ERROR-', str(e))
def main():
    stop_event = Event()
    layout = [
        [sg.Text('1亿以内自然数平方根之和计算器')],
        [sg.Text('计算进度:'), sg.ProgressBar(100, orientation='h', size=(30, 20), key='-PROGRESS-BAR-')],
        [sg.Multiline('', size=(50, 8), key='-OUTPUT-', autoscroll=True)],
        [sg.Text('结果:'), sg.Input('', key='-RESULT-', disabled=True, size=(30, 1))],
        [sg.Text('用时:'), sg.Input('', key='-TIME-', disabled=True, size=(15, 1)), sg.Text('秒')],
        [sg.Button('开始计算'), sg.Button('停止'), sg.Button('退出')]
    ]
    window = sg.Window('后台计算示例', layout, finalize=True)
    window['-PROGRESS-BAR-'].update(0)
    while True:
        event, values = window.read()
        if event in (sg.WIN_CLOSED, '退出'):
            stop_event.set()
            break
        elif event == '开始计算':
            window['-PROGRESS-BAR-'].update(0)
            window['-RESULT-'].update('')
            window['-TIME-'].update('')
            window['-OUTPUT-'].update('')
            stop_event.clear()
            window['开始计算'].update(disabled=True)
            window['停止'].update(disabled=False)
            # 启动后台线程
            window.start_thread(
                lambda: calculate_sqrt_sum(window, stop_event),
                '-THREAD-'
            )
        elif event == '停止':
            stop_event.set()
            window['停止'].update(disabled=True)
        # 处理来自线程的事件
        elif event == '-PROGRESS-':
            message, progress, result, elapsed = values[event]
            window['-OUTPUT-'].print(message)
            window['-PROGRESS-BAR-'].update(progress)
        elif event == '-DONE-':
            result, elapsed = values[event]
            window['-RESULT-'].update(f'{result:.4f}')
            window['-TIME-'].update(f'{elapsed:.2f}')
            window['-OUTPUT-'].print('计算完成!')
            window['开始计算'].update(disabled=False)
            window['停止'].update(disabled=True)
        elif event == '-CANCELED-':
            window['-OUTPUT-'].print('计算已取消')
            window['开始计算'].update(disabled=False)
            window['停止'].update(disabled=True)
        elif event == '-ERROR-':
            sg.popup_error(f'计算出错: {values[event]}')
            window['开始计算'].update(disabled=False)
            window['停止'].update(disabled=True)
    window.close()
if __name__ == '__main__':
    main()