PySimpleGUI滚动条尺寸更新问题及Frame使用报错排查
问题:PySimpleGUI滚动条更新报错及需求实现
问题详情
尝试实现动态添加内容时更新滚动条,调用window.visibility_changed()无效,且触发如下报错:
File "C:\...\Lib\site-packages\PySimpleGUI\PySimpleGUI.py", line 8302, in contents_changed self.TKColFrame.canvas.config(scrollregion=self.TKColFrame.canvas.bbox('all')) ^^^^^^^^^^^^^^^^^^^^^^ AttributeError: 'Frame' object has no attribute 'canvas'
测试代码:
import PySimpleGUI as sg def frame (n_frame): layout = [[sg.Text ('test')]] return layout def make_window(): layout = [[sg.Column([[sg.Text ('Title')], # First title of the IDS [sg.Column(frame(1),key = '-LVL 1 CALL-')], [sg.pin (sg.Frame(title = '', layout = [[sg.Button(' + ',key = '-ADD A LVL 1 FRAME-'), sg.Button(' - ',key = '-REMOVE A LVL 1 FRAME-'), sg.Button('Save')]], relief = 'flat'))]], scrollable=True, vertical_scroll_only=True, pad =(0,0))]] window = sg.Window('Window Title', layout, metadata=1, resizable = True, element_padding = (10, 6), finalize = True) return window def main(): window = make_window() while True: event, values = window.read() if event == sg.WIN_CLOSED or event =='Save': break elif event == '-ADD A LVL 1 FRAME-' : window.metadata += 1 window.extend_layout(window['-LVL 1 CALL-'],(frame(window.metadata))) window.refresh() window.visibility_changed() window['-LVL 1 CALL-'].contents_changed() window.close() if __name__ == '__main__': main()
额外需求
- 无需对新增的特定窗口调用
.contents_changed()即可更新滚动条尺寸 - 滚动条可随用户调整窗口大小自动适配内容
解决方案
报错原因
-LVL 1 CALL-是普通Column,未启用scrollable=True,仅带滚动条的Column才有canvas属性,因此调用.contents_changed()会触发属性错误。
修改后的实现代码
import PySimpleGUI as sg def frame(n_frame): return [[sg.Text(f'test {n_frame}')]] def make_window(): # 动态内容容器(带滚动条) dynamic_layout = [[sg.Text('Title')]] scroll_column = sg.Column( dynamic_layout, key='-SCROLL_COL-', scrollable=True, vertical_scroll_only=True, pad=(0, 0), expand_y=True # 允许垂直方向扩展 ) # 固定按钮栏 button_bar = sg.Frame( '', layout=[[ sg.Button(' + ', key='-ADD A LVL 1 FRAME-'), sg.Button(' - ', key='-REMOVE A LVL 1 FRAME-'), sg.Button('Save') ]], relief='flat', expand_x=True ) # 主布局 layout = [[scroll_column], [button_bar]] window = sg.Window( 'Window Title', layout, metadata=1, resizable=True, element_padding=(10, 6), finalize=True ) # 绑定窗口大小变化事件,自动更新滚动条 window.bind('<Configure>', '-WINDOW_RESIZED-') return window def main(): window = make_window() while True: event, values = window.read() if event == sg.WIN_CLOSED or event == 'Save': break elif event == '-ADD A LVL 1 FRAME-': window.metadata += 1 # 向滚动Column添加新内容 window.extend_layout(window['-SCROLL_COL-'], frame(window.metadata)) # 若要完全避免手动调用,可将此逻辑移至窗口 resize 事件统一处理 window['-SCROLL_COL-'].contents_changed() elif event == '-WINDOW_RESIZED-': # 窗口大小变化时自动适配滚动条 window['-SCROLL_COL-'].contents_changed() window.close() if __name__ == '__main__': main()
关键实现说明
- 滚动容器定位:将动态内容直接放在启用
scrollable=True的Column中,确保调用.contents_changed()的对象是带滚动条的容器。 - 自动适配窗口大小:通过绑定
<Configure>事件(窗口大小变化触发),自动调用滚动Column的.contents_changed()方法,实现滚动条随窗口尺寸动态调整。 - 简化手动调用:若要完全避免在添加内容时手动调用
.contents_changed(),可将滚动条更新逻辑统一移至窗口resize事件中,利用事件循环自动触发更新。
内容的提问来源于stack exchange,提问作者Enrra
相关产品推荐
相关产品推荐

