简体   繁体   中英

PySimpleGUI Listbox right click menu

I am wondering, is it possible to make the right click menu work on the selected box in the list box?

Example of a right click menu

右键菜单示例

I have succeeded in making a right click menu for the entire list box by doing

layout = [
        [gui.Listbox(size=(35, 22), key='chat', values=messages,
                     right_click_menu=['&Right', ['Delete', 'Favourite', 'Reply', 'Copy', 'Edit']])],
        [gui.InputText(key='input', size=(25, 10)), gui.Button('Send', bind_return_key=True, size=(9, 1))]
    ]

but its not quite what I am looking for. I want: if I right click on a box in the list box, said box will be selected and the actions of that menu will affect only that box. Lets say I right click on the middle box and press delete, the middle box will be deleted. I know how to work with the event of clicking the menu, but as of right now I have no way of actually telling which message was clicked.

It's possible, but need tkinter code and hack PySimleGUI code. Here new callback for Button 3, but selection for nearest one, not exact the one. Maybe sg.Table or sg.Tree can achieve better selection.

import PySimpleGUI as sg

def RightClickMenuCallback(event, element):
    widget = element.Widget
    current = widget.curselection()
    if current:
        widget.selection_clear(current[0])
    index = widget.nearest(event.y)
    widget.selection_set(index)
    element.TKRightClickMenu.tk_popup(event.x_root, event.y_root, 0)
    element.TKRightClickMenu.grab_release()

messages = [
    'This is the start of your chat!',
    'demo messages',
    'dont know what to right',
]

command = ['Delete', 'Favourite', 'Reply', 'Copy', 'Edit']
layout = [
    [sg.Listbox(size=(35, 22), key='chat', values=messages,
        right_click_menu=['&Right', command])],
    [sg.InputText(key='input', size=(25, 10)),
     sg.Button('Send', bind_return_key=True, size=(9, 1))],
]
window = sg.Window("Test", layout, finalize=True)
chat = window['chat']
chat.Widget.bind('<Button-3>', lambda event,
    element=chat: RightClickMenuCallback(event, element))

while True:

    event, values = window.read()
    if event == sg.WIN_CLOSED:
        break
    print(event, values)

window.close()

[Edit]

IMO, follow the way provided by library should be preferred.

import PySimpleGUI as sg

messages = [
    'This is the start of your chat!',
    'demo messages',
    'dont know what to right',
]

command = ['Delete', 'Favourite', 'Reply', 'Copy', 'Edit']
cmd_layout = [[sg.Button(cmd, size=(10, 1))] for cmd in command]
layout = [
    [sg.Listbox(values=messages, size=(35, 22), key='chat'),
     sg.Column(cmd_layout)],
    [sg.InputText(key='input', size=(25, 10)),
     sg.Button('Send', bind_return_key=True, size=(9, 1))],
]
window = sg.Window("Test", layout, finalize=True)
window['input'].expand(expand_x=True)

while True:

    event, values = window.read()
    if event == sg.WIN_CLOSED:
        break
    print(event, values)

window.close()

Add option enable_events=True to sg.Listbox if you need event generated when mouse button 1 clicked. When any event generated, you can get the list of items currently selected in this listbox by values['chat'] or window['chat'].get() , now there's only one item selected, so message is values['chat'][0] .

If you need index, you have to call window['chat'].get_indexes() , it returns the items currently selected as a list of indexes. So, the same, get index of selected item by window['chat'].get_indexes()[0]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM