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
[ Question] Is it possible for me to force update the values dictionary for my menubutton elements to None? #6734
Comments
I believe you can provide a short program that isolates and demonstrates the problem. There's no method provide to reset the value of a MenuButton element for menu item chosen. Try following code if it is about your question. import PySimpleGUI as sg
menu_def = ['', ['red', 'orange', 'yellow', 'green', 'blue', 'white', 'brown', 'black']]
layout = [
[sg.ButtonMenu("", menu_def=menu_def, expand_x=True, button_color=(None, sg.theme_background_color()), key=("BM", i)) for i in range(5)],
[sg.Button(key) for key in ("Clear", "Check", "Quit")],
]
window = sg.Window("Title", layout)
while True:
event, values = window.read()
if event in (sg.WIN_CLOSED, "Quit"):
break
print(event, [value for key, value in values.items()])
if event[0] == "BM":
window[event].update(button_color=(None, values[event]))
elif event == "Clear":
for i in range(5):
window[("BM", i)].update(button_color=(None, sg.theme_background_color()))
window[("BM", i)].MenuItemChosen = None
window.close() ('BM', 1) [None, 'yellow', None, None, None]
('BM', 3) [None, 'yellow', None, 'blue', None]
Clear [None, 'yellow', None, 'blue', None] # The values is generated after event "Check", not after this event processed.
Check [None, None, None, None, None] |
Thank you, thank you for such a quick reply!! The .MenuItemChosen method is the one that I needed :) Just for future reference are these methods listed in the documentation anywhere? I may be being daft but I searched for the method above and couldn't find anything. I think I took the guidance for issues where it said to "include your layout and window call" a little too literally, ha. I didn't realise I could post a piece of representative code instead. I'll do that next time. I've never come across a package with such fantastic support, thank you to you and everyone that works on it. |
Looking at the code, it looks like this may be a bug. There is a bit of commented out code that includes clearing the chosen item just as the Menu element does. It may have happened when the CustomTitlebar was added. If so, then it's a bug and I can safely revert it back to the old way.... more investigation.... |
OK! Fixed in 5.0.4.2
Using @jason990420's excellent sample code, here's it running on 5.0.4.2 pycharm64_xG5WfSu3jJ.mp4 |
After fixed, user code won't work now. IMO, programmer need to find another way to keep and check the state of each ButtonMenu element. import PySimpleGUI as sg
menu_def = ['', ['red', 'orange', 'yellow', 'green', 'blue', 'white', 'brown', 'black']]
layout = [
[sg.ButtonMenu("", menu_def=menu_def, expand_x=True, button_color=(None, sg.theme_background_color()), key=("BM", i)) for i in range(5)],
[sg.Button(key) for key in ("Clear", "Check", "Quit")],
]
window = sg.Window("Title", layout)
states = {}
while True:
event, values = window.read()
if event in (sg.WIN_CLOSED, "Quit"):
break
elif event[0] == "BM":
window[event].update(button_color=(None, values[event]))
states[event] = values[event]
elif event == "Clear":
for i in range(5):
window[("BM", i)].update(button_color=(None, sg.theme_background_color()))
states = {}
print(len(states), event, states)
window.close() 1 ('BM', 1) {('BM', 1): 'yellow'}
2 ('BM', 2) {('BM', 1): 'yellow', ('BM', 2): 'blue'}
3 ('BM', 4) {('BM', 1): 'yellow', ('BM', 2): 'blue', ('BM', 4): 'brown'}
0 Clear {} |
This is the same thoughts I was having when fixing it. The event and values when the choice is made is that something happened. It's up to the user's code to remember this is a way that makes sense to them. They would even be a simple list because the position never changes for each spot. Menu choices are a 1-time kind of thing, like a button click. They come, they go... if it's important to you, you save it somewhere. Sorry that the behavior changed in a way that may have been relied on. The new code really is how it was originally design and has worked for most of the PySimpleGUI lifetime. I do appreciate that the issues was opened and led to finding this bug! |
Side note for @jason990420 .... I loved seeing this in your code: elif event[0] == "BM": This Python construct of being able to reference a string with [0] or a tuple and then compare to a string makes the event processing of both events that are plain strings and events that are tuples to be mixed together without problems. I'm great that we don't have to look at the type of the event variable first as it adds complexity. Here's a version of Jason's code modified to use a list to store the current state of the board. import PySimpleGUI as sg
menu_def = ['', ['red', 'orange', 'yellow', 'green', 'blue', 'white', 'brown', 'black']]
layout = [
[sg.ButtonMenu("", menu_def=menu_def, expand_x=True, button_color=(None, sg.theme_background_color()), key=("BM", i)) for i in range(5)],
[sg.Button(key) for key in ("Clear", "Check", "Quit")],
]
window = sg.Window("Title", layout)
states = ['' for i in range(5)] # start with cleared states
while True:
event, values = window.read()
if event in (sg.WIN_CLOSED, "Quit"):
break
elif event[0] == "BM":
window[event].update(button_color=(None, values[event]))
states[event[1]] = values[event]
elif event == "Clear":
for i in range(5):
window[("BM", i)].update(button_color=(None, sg.theme_background_color()))
states[i] = ''
print(event, states)
window.close() With sample output
|
Hi both, Wow, I've been without internet for a couple of days and you've done a lot! Firstly, glad this helped find a bug :) Secondly, I agree, clearing after the event feels like a more sensible behaviour for the menu buttons. As suggested I'll modify my code to capture the current state of the button. Thank you for the suggestions above - particularly using a tuple for the button key, didn't know that was possible and now I can get rid of all my horrible string splitting in favour of nice Pythonic indexing :) |
I'm genuinely thrilled you're clearly enjoying using PySimpleGUI. You can read more about using datatypes other than strings for keys here: There are examples in the Demo Programs and Cookbook as well showing tuples as keys. It's a very useful construct as you've seen. I use tuples when a thread is sending events to the GUI. This enables me to use the first entry of the tuple to tell the event loop that the event is coming from the thread. The other entries in the tuple can carry any kind of data I want. Here's a Demo Program that shows this design pattern: |
Type of Issue (Enhancement, Error, Bug, Question)
Question
Operating System
Windows 11 Home, OS build: 22631.3296
PySimpleGUI Port (tkinter, Qt, Wx, Web)
tkinter
Versions
Version information can be obtained by calling
sg.main_get_debug_data()
Or you can print each version shown in ()
Python Interpeter: C:\Users\lily-\anaconda3\python.exe
Python version: 3.11.7
Platform: Windows
Platform version: ('10', '10.0.22631', 'SP0', 'Multiprocessor Free')
Port: PySimpleGUI
tkinter version: 8.6.12
PySimpleGUI version: 5.0.4
PySimpleGUI filename: C:\Users\lily-\anaconda3\Lib\site-packages\PySimpleGUI\PySimpleGUI.py
Python version (
sg.sys.version
)3.11.7 | packaged by Anaconda, Inc. | (main, Dec 15 2023, 18:05:47) [MSC v.1916 64 bit (AMD64)]
PySimpleGUI Version (
sg.__version__
)'5.0.4'
GUI Version (tkinter (
sg.tclversion_detailed
), PySide2, WxPython, Remi)Your Experience In Months or Years (optional)
Years Python programming experience
2/3 as a hobbyist
Years Programming experience overall
see above
Have used another Python GUI Framework? (tkinter, Qt, etc) (yes/no is fine)
No
Anything else you think would be helpful?
This is my first PySimpleGUI project!
Troubleshooting
These items may solve your problem. Please check those you've done by changing - [ ] to - [X]
Detailed Description
I am building a GUI to allow the user to play the "Mastermind" logic game against the computer (see image below). The user inputs 5 colours in a row each time (using MenuButtons) and then when the "Submit Guess" button is clicked the users inputs are then checked against the predefined 5 colour solution and feedback given.
When users click the "Submit Guess" button a method is called which checks if any of the colours haven't been set (ie. if the items in the values dict for the keys in that row are equal to None) and notifies the user that this is an invalid guess. This works very well until a new game is started using the "New" button. The values dictionary for the MenuButtons are retained from the previous game so this method no longer detects an invalid submission and in fact if buttons are left blank it uses the values from the previous game.
I would like to know if there is a way to force update the values dictionary to have value = None for all these elements. So far I've tried:
I'm sorry the code below is long - I couldn't find a way to make it run with only the problem parts in. Hopefully it might be possible to suggest a solution from the description above...? Also I'm sure some of the code is probably very GRIM! This is my first PySimpleGUI and I'm still reasonably new to Python so forgive the rough edges! :)
Code To Duplicate
A short program that isolates and demonstrates the problem (Do not paste your massive program, but instead 10-20 lines that clearly show the problem)
This pre-formatted code block is all set for you to paste in your bit of code:
Screenshot, Sketch, or Drawing
Watcha Makin?
If you care to share something about your project, it would be awesome to hear what you're building.
See description above - this is only halfway finished but should be a fun game when it is done!
The text was updated successfully, but these errors were encountered: