PySimpleGUI切换布局后窗口无法恢复原尺寸问题求助
问题描述
我开发了一款通过菜单选择切换不同布局的PySimpleGUI程序,当切换至Log By Grep(Dashboard风格)布局后再切回其他常规布局时,窗口无法像另外两个布局一样恢复原始尺寸。
以下是相关代码:
import _thread import PySimpleGUI as sg import paramiko import math # pylint: disable=C0103 ,W0612, C0301, R1722 client = paramiko.SSHClient() def ssh_connect(HOSTNAME,key_num): print(HOSTNAME) '''Connect to SDR with mobaxterm SSH connection''' hostname = HOSTNAME username = "air" password = "d1password1" port = 22 # add to known hosts client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: window[f'-LOG-{key_num}'].update("Trying to Connect..." + '\n', append=True) client.connect(hostname=hostname, username=username, password=password, port=port) print(f"Connected to SSH - IP : {hostname} Nashville") window[f'-LOG-{key_num}'].update(f"Connected to SSH - IP : {hostname}" + '\n', append=True) except ValueError as error: print("[!] Cannot connect to the SSH Server") window[f'-LOG-{key_num}'].update("[!] Cannot connect to the SSH Server" + '\n', append=True) exit() def system_time(): '''Takes the system time from mobaxterm SSH connection''' stdinn, start, stderrr = client.exec_command("date '+%Y-%m-%d %H:%M:%S,%3N'") sys_time = start.read().decode() return sys_time def App_loger(): '''Data collection proccess''' global stop # New statement start_time = system_time() accumulated_detections = 0 while not stop: # New statement stop_time = system_time() stdin, grep, stderr = client.exec_command(f"cat /var/log/enforce-air/enforce-air.log |" " grep -E 'DL: Chain: 11, Task: Detect.*F: '|" f"awk -v 'start={start_time}' -v end='{stop_time}' " "'/^[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2} ""/"" {inrange = $0 >= start && $0 <= end } inrange' |" "awk -F '|' '{print $7}' |awk -F ',' '{print $8 ',' $12}'") x = grep.read().decode() x = x.split('\n') if len(x) > 1: for line in x: window['-LOG-1'].update(line + '\n', append=True) accumulated_detections = accumulated_detections + len(x) - 1 window['-NUM_OF_DETECTIONS-1'].update(str(accumulated_detections)) # window.refresh() start_time = stop_time def log_finder_grep(cus_grep): '''Data collection proccess''' global stop_4 # New statement custom_grep = cus_grep start_time = system_time() accumulated_detections = 0 while not stop_4: # New statement stop_time = system_time() stdin, grep, stderr = client.exec_command(f"cat /var/log/enforce-air/enforce-air.log |" f" grep -E '{custom_grep}'|" f"awk -v 'start={start_time}' -v end='{stop_time}' " "'/^[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2} ""/"" {inrange = $0 >= start && $0 <= end } inrange'") y = grep.read().decode() y = y.split('\n') if len(y) > 1: for line in y: window['-LOG-4'].update(line + '\n', append=True) accumulated_detections = accumulated_detections + len(y) - 1 window['-NUM_OF_DETECTIONS-1'].update(str(accumulated_detections)) # window.refresh() start_time = stop_time theme_dict = {'BACKGROUND': '#2B475D', 'TEXT': '#FFFFFF', 'INPUT': '#F2EFE8', 'TEXT_INPUT': '#000000', 'SCROLL': '#F2EFE8', 'BUTTON': ('#000000', '#C2D4D8'), 'PROGRESS': ('#FFFFFF', '#C7D5E0'), 'BORDER': 1,'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0} sg.LOOK_AND_FEEL_TABLE['Dashboard'] = theme_dict sg.theme('Dashboard') BORDER_COLOR = '#C7D5E0' DARK_HEADER_COLOR = '#1B2838' BPAD_TOP = ((20,20), (20, 10)) BPAD_LEFT = ((20,10), (0, 10)) BPAD_LEFT_INSIDE = ((0, 10),(0, 10)) BPAD_RIGHT = ((10,20), (10, 20)) menu_def = [['Apps', ['SSH Logger', 'FSPL Calculator', 'Log By Grep', 'Exit APP', ]], ['Edit', ['Paste', ['Special', 'Normal', ], 'Undo'], ], ['Help', 'About...'], ] top_banner = [[sg.Text('Enter HostName'), sg.InputText(size=(15, 1), key='HOSTNAME_4'), sg.Button('Connect to SSH', key='Connect to SSH 4', size=(15, 1))], [sg.Text('Enter Grep'), sg.InputText(size=(100, 10), key='custom_grep')]] block_3 = [ [sg.Button('Drone_Detect',key='drone_detect_button', size=(29, 1))], [sg.Button('RC_Detect',key='rc_detect_button', size=(29, 1))], [sg.Button('1',key='1', size=(29, 1))], [sg.Button('2',key='2', size=(29, 1))], [sg.Button('3',key='3', size=(29, 1))], [sg.Button('4',key='4', size=(29, 1))], [sg.Button('5',key='5', size=(29, 1))], [sg.Button('6',key='6', size=(29, 1))], [sg.Button('Go'), sg.Button('Exit')]] block_2 = [[sg.Button('Run', key='Run_4'), sg.Button('Stop', key='Stop_4'),sg.Button('Exit', key='Exit_4', button_color=('white', 'red'))], [sg.Text('accumulated_detections'), sg.Multiline(size=(8, 1), key='-NUM_OF_DETECTIONS-1', do_not_clear=True, autoscroll=True, auto_refresh=True, write_only=False, disabled=True)]] block_4 = [[sg.Multiline(size=(116, 33), key='-LOG-4', do_not_clear=True, autoscroll=True, auto_refresh=True, write_only=False, disabled=True)]] FSPL_Calculator_layout = [[sg.Text('Enter Freq[Ghz] '), sg.InputText(key='-DIST-', size=(8, 1)), sg.Text('Result[dBm]:'), sg.Multiline(size=(8, 1), key='result', do_not_clear=True, autoscroll=True, auto_refresh=True, write_only=False, disabled=True)], [sg.Text('Enter Distance[m]'), sg.InputText(key='-FREQ-', size=(8, 1))], [sg.Button('Calculate', size=(10, 1)), sg.Button('Exit', key='Exit_3 ', size=(10, 1))]] Parser_log_yariv = [[sg.Text('Enter HostName'), sg.InputText(size=(15, 1), key='HOSTNAME_1'), sg.Button('Connect to SSH', key='Connect to SSH 1', size=(15, 1))], [sg.Multiline(size=(50, 20), key='-LOG-1', do_not_clear=True, autoscroll=True, auto_refresh=True, write_only=False, disabled=True)], [sg.Text('accumulated_detections'), sg.Multiline(size=(8, 1), key='-NUM_OF_DETECTIONS-1', do_not_clear=True, autoscroll=True, auto_refresh=True, write_only=False, disabled=True), sg.Button('Run', key='Run_1'), sg.Button('Stop', key='Stop_1'), sg.Button('Exit', key='Exit_1', button_color=('white', 'red'))]] Open_image_layout = [[sg.Image('image.png', size=(400, 400))]] layout = [[[sg.Column(FSPL_Calculator_layout, key='FSPL_Calc', visible=False), sg.Column(Open_image_layout, key='Open_image', visible=True),sg.Column(Parser_log_yariv, key='Parser_log_yariv', visible=False), sg.Column(top_banner, size=(1120, 70), pad=(20, 0), background_color=DARK_HEADER_COLOR, key='log_by_grep_1', visible=False)], [sg.Column([[sg.Column(block_2, size=(250, 80), pad=BPAD_LEFT_INSIDE, key='log_by_grep_2', visible=False)], [sg.Column(block_3, size=(250, 450), pad=BPAD_LEFT_INSIDE)]], pad=BPAD_LEFT, background_color=BORDER_COLOR, key='log_by_grep_3', visible=False), sg.Column(block_4, size=(850, 550), pad=BPAD_RIGHT, key='log_by_grep_4', visible=False)]], [sg.Menu(menu_def)]] window = sg.Window('Dashboard PySimpleGUI-Style', layout, margins=(0,0), background_color=BORDER_COLOR, no_titlebar=True, grab_anywhere=True) stop = False while True: # Event Loop event, values = window.read() if event == 'SSH Logger': window['log_by_grep_1'].update(visible=False) window['log_by_grep_2'].update(visible=False) window['log_by_grep_3'].update(visible=False) window['log_by_grep_4'].update(visible=False) window['FSPL_Calc'].update(visible=False) window['Parser_log_yariv'].update(visible=True) window['Open_image'].update(visible=False) if event == "Connect to SSH 1": ssh_connect(values['HOSTNAME_1'],'1') if event == "Run_1": stop = False # New statement window['Run_1'].update(button_color=('black', 'yellow')) _thread.start_new_thread(App_loger, ()) # New statement if event == "Stop_1": stop = True # New statement if event == "Exit_1" or event == sg.WIN_CLOSED: window.Close() # New statement break ######################################################################################################################## if event == 'FSPL Calculator': window['log_by_grep_1'].update(visible=False) window['log_by_grep_2'].update(visible=False) window['log_by_grep_3'].update(visible=False) window['log_by_grep_4'].update(visible=False) window['FSPL_Calc'].update(visible=True) window['Parser_log_yariv'].update(visible=False) window['Open_image'].update(visible=False) if event == "Calculate": freq = values['-FREQ-'] dist = values['-DIST-'] print(values['-FREQ-']) FSPL = 20 * math.log(float(freq) * 1000000000, 10) + 20 * math.log(float(dist), 10) - 147.55 FSPL = round(FSPL, 2) window['result'].update(str(FSPL)) if event == "Exit_3 " or event == sg.WIN_CLOSED: window.Close() # New statement break ######################################################################################################################## if event == 'Log By Grep': window['log_by_grep_1'].update(visible=True) window['log_by_grep_2'].update(visible=True) window['log_by_grep_3'].update(visible=True) window['log_by_grep_4'].update(visible=True) window['FSPL_Calc'].update(visible=False) window['Parser_log_yariv'].update(visible=False) window['Open_image'].update(visible=False) print(layout) if event == "Connect to SSH 4": ssh_connect(values['HOSTNAME_4'],'4') if event == "drone_detect_button": stop_4 = False # New statement values['custom_grep'] = 'drone_detect' args = (values['custom_grep']) _thread.start_new_thread(log_finder_grep, (args,)) if event == "Run_4": stop_4 = False # New statement window['Run_4'].update(button_color=('black', 'yellow')) args = (values['custom_grep']) _thread.start_new_thread(log_finder_grep, (args, )) # New statement if event == "Stop_4": stop_4 = True if event == "Exit_4" or event == sg.WIN_CLOSED: window.Close() break if event == "Exit APP" or event == sg.WIN_CLOSED: window.Close() # New statement break if event == sg.WIN_CLOSED or event == 'Exit': break window.close()
解决方案
问题根源
Log By Grep布局中大量使用了固定尺寸的Column控件(比如size=(1120,70)、size=(850,550)),这些固定尺寸会强制窗口拉伸到对应大小;而其他布局的控件没有设置这么大的固定尺寸,切换时PySimpleGUI不会自动收缩窗口到适配新布局的最小尺寸。
修改步骤
移除固定尺寸限制:删除
Log By Grep相关所有Column的size参数,让PySimpleGUI自动根据控件内容计算布局尺寸。
示例修改后的布局定义:layout = [[[sg.Column(FSPL_Calculator_layout, key='FSPL_Calc', visible=False), sg.Column(Open_image_layout, key='Open_image', visible=True), sg.Column(Parser_log_yariv, key='Parser_log_yariv', visible=False), sg.Column(top_banner, pad=(20, 0), background_color=DARK_HEADER_COLOR, key='log_by_grep_1', visible=False)], [sg.Column([[sg.Column(block_2, pad=BPAD_LEFT_INSIDE, key='log_by_grep_2', visible=False)], [sg.Column(block_3, pad=BPAD_LEFT_INSIDE)]], pad=BPAD_LEFT, background_color=BORDER_COLOR, key='log_by_grep_3', visible=False), sg.Column(block_4, pad=BPAD_RIGHT, key='log_by_grep_4', visible=False)]], [sg.Menu(menu_def)]]切换布局后强制适配尺寸:在每个布局切换的代码块末尾,添加
window.set_size((None, None)),让窗口自动调整到当前可见布局的最小适配尺寸。
示例(以切换到SSH Logger布局为例):if event == 'SSH Logger': window['log_by_grep_1'].update(visible=False) window['log_by_grep_2'].update(visible=False) window['log_by_grep_3'].update(visible=False) window['log_by_grep_4'].update(visible=False) window['FSPL_Calc'].update(visible=False) window['Parser_log_yariv'].update(visible=True) window['Open_image'].update(visible=False) window.set_size((None, None)) # 添加此行,自动调整窗口尺寸需为
SSH Logger、FSPL Calculator、Log By Grep三个布局切换事件都添加这行代码。优化线程变量初始化:在代码开头添加
stop_4 = False,避免切换到Log By Grep布局时出现未定义变量的错误。
内容的提问来源于stack exchange,提问作者skyline
相关产品推荐
相关产品推荐

