如何实现Listbox项拖拽至Workspace?PySimpleGUI拖拽故障排查
问题描述
我希望实现将Listbox中的内容以块形式拖拽到Workspace中,类似Scratch的操作逻辑。我给PySimpleGUI的Listbox添加了draggable=True参数,但Listbox内的项仍无法被拖拽。相关代码如下:
import PySimpleGUI as sg from PIL import ImageGrab # 创建要显示的代码列表 code_lines = [ "variable", "loops", "types of variables" ] # 创建窗口布局 layout = [ [sg.Column([[sg.Listbox(values=code_lines, size=(20, 10), key='Python Code', draggable = True)]]), sg.Column([[sg.Text('Workspace:', size=(20, 1)), sg.Multiline(size=(50, 30), key='workspace', background_color='dark gray')]])], [sg.Button('Close')] ] # 创建窗口 window = sg.Window('PyDrop', layout) # 事件循环处理事件 while True: event, values = window.read() if event == sg.WIN_CLOSED or event == 'Close': # 用户关闭窗口或点击关闭按钮 break elif event == 'Python Code': # 用户点击Listbox中的项 # 存储点击项的值 dragged_item = values['Python Code'][0] elif event == sg.DRAG: # 用户按住按钮移动鼠标 # 更新目标区域的值 print('Drag event triggered') window['drop_target'].update(dragged_item) # 关闭窗口 window.close()
解决方案
PySimpleGUI中Listbox的draggable参数作用是让整个Listbox控件可拖拽,而非内部的单个列表项。要实现列表项拖拽到Workspace的效果,需要手动绑定鼠标事件来处理:
- 记录鼠标左键按下时选中的列表项
- 监听鼠标释放事件,判断释放位置是否处于Workspace区域内
- 若位置符合,则将选中项添加到Workspace中
修改后的代码如下:
import PySimpleGUI as sg code_lines = [ "variable", "loops", "types of variables" ] # 定义窗口布局 layout = [ [ sg.Column([[sg.Listbox(values=code_lines, size=(20, 10), key='Python Code', enable_events=True)]]), sg.Column([[sg.Text('Workspace:'), sg.Multiline(size=(50, 30), key='workspace', background_color='dark gray')]], key='WorkspaceCol') ], [sg.Button('Close')] ] window = sg.Window('PyDrop', layout, finalize=True) # 获取Workspace列的位置和尺寸,用于判断拖拽释放位置 workspace_col = window['WorkspaceCol'] workspace_rect = workspace_col.get_bbox() dragged_item = None while True: event, values = window.read(timeout=10) if event == sg.WIN_CLOSED or event == 'Close': break # 鼠标左键按下Listbox项时,记录选中内容 elif event == 'Python Code' and window.mouse_buttons_pressed == (True, False, False): if values['Python Code']: dragged_item = values['Python Code'][0] # 鼠标释放时,判断是否在Workspace区域内 elif event == sg.EVENT_MOUSE_UP: if dragged_item: mouse_x, mouse_y = window.mouse_location() # 检查鼠标位置是否处于Workspace列的范围内 if (workspace_rect[0] <= mouse_x <= workspace_rect[2] and workspace_rect[1] <= mouse_y <= workspace_rect[3]): # 将拖拽项追加到Workspace中 current_content = values['workspace'] window['workspace'].update(current_content + dragged_item + '\n') dragged_item = None window.close()
关键说明
- 给Listbox添加
enable_events=True,确保能触发点击事件 - 通过
window.mouse_buttons_pressed判断鼠标左键按下状态,记录选中的列表项 - 监听
sg.EVENT_MOUSE_UP事件,结合window.mouse_location()和Workspace的位置范围,判断拖拽是否完成 - 若拖拽到目标区域,将选中项追加到Multiline控件中,模拟Scratch的块添加逻辑
内容的提问来源于stack exchange,提问作者Cole Davidson
相关产品推荐
相关产品推荐

