Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Enhancement] Reusing Context Menu #6758

Open
1 of 10 tasks
Whitelegs opened this issue May 17, 2024 · 6 comments
Open
1 of 10 tasks

[Enhancement] Reusing Context Menu #6758

Whitelegs opened this issue May 17, 2024 · 6 comments
Labels
Done - Install Dev Build (see docs for how) See https://docs.pysimplegui.com/en/latest/documentation/installing_licensing/upgrading/ enhancement New feature or request Port - TK PySimpleGUI

Comments

@Whitelegs
Copy link

Type of Issue (Enhancement, Error, Bug, Question)

Enhancement


Environment

Operating System

Linux version ('glibc', '2.35')

PySimpleGUI Port (tkinter, Qt, Wx, Web)

tkinter


Versions

Python version (sg.sys.version)

3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0]

PySimpleGUI Version (sg.__version__)

5.0.4.15

GUI Version (tkinter (sg.tclversion_detailed), PySide2, WxPython, Remi)

8.6.12


Your Experience In Months or Years (optional)

Years Python programming experience
Years Programming experience overall
No Have used another Python GUI Framework? (tkinter, Qt, etc) (yes/no is fine)


Troubleshooting

These items may solve your problem. Please check those you've done by changing - [ ] to - [X]

  • Searched main docs for your problem https://Docs.PySimpleGUI.com
  • Looked for Demo Programs that are similar to your goal.
    It is recommend you use the Demo Browser! https://Demos.PySimpleGUI.com
  • If not tkinter - looked for Demo Programs for specific port
  • For non tkinter - Looked at readme for your specific port if not PySimpleGUI (Qt, WX, Remi)
  • None of your GUI code was generated by an AI algorithm like GPT
  • Run your program outside of your debugger (from a command line)
  • Searched through Issues (open and closed) to see if already reported https://Issues.PySimpleGUI.com
  • Have upgraded to the latest release of PySimpleGUI on PyPI (latest official version) https://Upgrading.PySimpleGUI.com
  • Tried running the Maintenance Release. Use Home Window to access Maint Releases
  • For licensing questions please email mailto:license@PySimpleGUI.com

Detailed Description

Unless I'm missing something I think the context menu in general should return the underlying element in the same way as a context menu does on a button. As it stands you cannot reuse the same context menu on different fields. You can of course create a separate menu for each with different keys attached but this seems an inefficient way of doing things.

From the code below I have no easy way to determine if the user is on the size or color field and just right clicks on the field. If the user tabs through so that the field gets the focus I can use window.find_element_with_focus().key to do that but with a mouse it just doesn't work. Binding & to the Combo key and then to '+MNU' sort of works; however if the user right clicks on size and, without clearing that then right clicks on the color field the color context menu is activated but mouse entry/exit events are not flagged so you can't pick up the relevant field.

Code To Duplicate

import PySimpleGUI as sg
size_vals = ['Small', 'Medium', 'Large']
color_vals = ['Red', 'Blue', 'Green']

combo_mnu = ['', ['Clear', '---', 'Add', 'Delete']]

layout = [
          [sg.Text('Size:', size=10), sg.Combo(size_vals, size=15,
                                                      default_value='Medium', key='-SIZE', enable_events=True,
                                                      right_click_menu=combo_mnu)],
          [sg.Text('Color:', size=10), sg.Combo(color_vals, size=15,
                                                default_value='Red',key='-COLOR', enable_events=True, right_click_menu=combo_mnu)],
          [sg.OK(), sg.Cancel()]
          ]


win = sg.Window('test', layout=layout, finalize=True, return_keyboard_events=True)
win['-SIZE'].bind('<Enter>', '+ENTER')
win['-COLOR'].bind('<Leave>', '+EXIT')
win['-SIZE'].bind('<Button-3>', '+MNU')
win['-COLOR'].bind('<Button-3>', '+MNU')


while True:
    event, values = win.read()
    if event in (sg.WIN_CLOSED, 'Cancel', '-CANCEL', 'CANCELB'):
        break
    if event is None:
        continue
    try:
        focused = win.find_element_with_focus().key
    except AttributeError:
        continue
    print(event, values, focused)

Screenshot, Sketch, or Drawing

@PySimpleGUI PySimpleGUI added enhancement New feature or request Done - Install Dev Build (see docs for how) See https://docs.pysimplegui.com/en/latest/documentation/installing_licensing/upgrading/ Port - TK PySimpleGUI labels May 17, 2024
@PySimpleGUI
Copy link
Owner

Somewhat experimental, but let's give it a try.... I may not be understanding what you're after, but this is a solution I came up with given a few minutes this morning.

Added in 5.0.4.16 a new window member variable right_click_menu_element which will be None if no element can be determined that was right clicked... or it'll have the element object that was right clicked (assuming a right click menu was chosen.

import PySimpleGUI as sg

layout = [  [sg.Text('Right click element test')],
            [sg.Input(key='-IN-')],
            [sg.Text(size=(12,1), key='-OUT-')],
            [sg.Button('Go'), sg.Button('Exit')]  ]

window = sg.Window('Window Title', layout, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, print_event_values=True)

while True:
    event, values = window.read()
    if event == sg.WIN_CLOSED or event == 'Exit':
        break
    if event == 'Go':
        window['-OUT-'].update(values['-IN-'])
    if window.right_click_menu_element:
        key = window.right_click_menu_element.key
    else:
        key = 'do not know'
    print(f'Right click elem key = {key}')
window.close()

@PySimpleGUI
Copy link
Owner

You can of course create a separate menu for each with different keys attached but this seems an inefficient way of doing things.

This was the intended direction for users to take. It's one of the reasons Menu items have keys that you can use.

A menu is a list. Making a copy and add keys is not difficult nor particularly inefficient since it's a few bytes and 1 line of code.

@PySimpleGUI
Copy link
Owner

PySimpleGUI commented May 17, 2024

Here's an example of individual menus for a couple of the elements.

import PySimpleGUI as sg
import copy

orig_menu =  ['', ['Edit Me', 'Version', 'Exit']]
menu1 = copy.deepcopy(orig_menu)
menu2 = copy.deepcopy(orig_menu)
menu1[1] = [f'{m}::-IN-' for m in menu1[1]]
menu2[1] = [f'{m}::-OUT-' for m in menu2[1]]

layout = [  [sg.Text('Right click element test')],
            [sg.Input(key='-IN-', right_click_menu=menu1)],
            [sg.Text('Text element for output', key='-OUT-', right_click_menu=menu2)],
            [sg.Button('Go'), sg.Button('Exit')]  ]

window = sg.Window('Window Title', layout, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, print_event_values=True)

while True:
    event, values = window.read()
    if event == sg.WIN_CLOSED or event == 'Exit':
        break
    if '::' in event:
        print(f'key from menu is {event.split("::")[1]}')
window.close()

This one may be even better as you don't need to do a copy.

import PySimpleGUI as sg

orig_menu =  ['', ['Edit Me', 'Version', 'Exit']]

menu1 = ['', [f'{m}::-IN-' for m in orig_menu[1]]]
menu2 = ['', [f'{m}::-OUT-' for m in orig_menu[1]]]

layout = [  [sg.Text('Right click element test')],
            [sg.Input(key='-IN-', right_click_menu=menu1)],
            [sg.Text('Text element for output', key='-OUT-', right_click_menu=menu2)],
            [sg.Button('Go'), sg.Button('Exit')]  ]

window = sg.Window('Window Title', layout, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, print_event_values=True)

while True:
    event, values = window.read()
    if event == sg.WIN_CLOSED or event == 'Exit':
        break
    if '::' in event:
        print(f'key from menu is {event.split("::")[1]}')
window.close()

@Whitelegs
Copy link
Author

Fair enough; when I first started programming back in the late 70s (yes, pre-dating PCs & DOS) we couldn't afford to duplicate code & it's stuck with me ever since. That does seem to be the best option in this case though, particularly your last suggestion so I'll roll with that. Thanks.

@PySimpleGUI
Copy link
Owner

when I first started programming back in the late 70s we couldn't afford to duplicate code

You and me both.... 4K of RAM in my first computer. CPM machines and 6502 processors didn't have many resources to begin with.

I've got 128 GB of RAM now now.

image

It took a while when I got back into programming with Python to redefine my definitions of large, inefficient, etc.

Generally speaking, if a tradeoff is between simplicity and resource use, simplicity often wins, especially when the resources are so small.

Some of the concepts we learned back then, like stability, memory leaks, race conditions, etc, haven't changed in their importance.

Thank you for the "thanks" image . Seeing it never fails to make me smile. And thanks for the comment on the code solution. I hadn't done anything quite like it so your question got me to try solving a new problem. Good stuff.... keep building! Sounds like you're making an excellent interface.

@Whitelegs
Copy link
Author

Aah, the good old days. It was all so new, fun & exciting then. The first computer I owned was a Sinclair ZX81 with 1k of memory, plugged into the TV & a cassette player for storage. Amazing what you could do with it though. I subsequently paid a small fortune for an expansion pack which took it to an enormous 16K. I remember how proud I was when I eventually wrote a 'word-processor' (more like a text editor these days) with fonts, justification etc within that memory & being able to save & load it from cassette. Took an age to read & write but it all worked within that minuscule amount of memory.
Cheers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Done - Install Dev Build (see docs for how) See https://docs.pysimplegui.com/en/latest/documentation/installing_licensing/upgrading/ enhancement New feature or request Port - TK PySimpleGUI
Projects
None yet
Development

No branches or pull requests

2 participants