Comments (10)
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 :)
from pysimplegui.
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.
from pysimplegui.
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.
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.
For example, it can be done by using an user_defined dict variable, like the dict-variable states
here.
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 {}
from pysimplegui.
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
('BM', 1) ['', 'yellow', '', '', '']
('BM', 0) ['orange', 'yellow', '', '', '']
('BM', 4) ['orange', 'yellow', '', '', 'white']
Check ['orange', 'yellow', '', '', 'white']
Check ['orange', 'yellow', '', '', 'white']
Clear ['', '', '', '', '']
('BM', 4) ['', '', '', '', 'blue']
from pysimplegui.
I'm genuinely thrilled you're clearly enjoying using PySimpleGUI.
You can read more about using datatypes other than strings for keys here:
https://docs.pysimplegui.com/en/latest/documentation/module/keys/#tuples-and-other-data-types-as-keys
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:
https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multithreaded_Write_Event_Value.py
from pysimplegui.
I'm sorry the code below is long - I couldn't find a way to make it run with only the problem parts in.
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]
from pysimplegui.
Thank you for the many kind words It's very appreciated!
Looks like we need to add a "clear choice" feature to Button Menus, and maybe a "set choice" too. PySimpleGUI is certainly a work in progress that will never be "done". I didn't realize that the choice "stuck" in the values
dictionary. Normal Menubars clear the value once the event has passed. Something tells me there's a reason for this, but I don't recall what it is just yet. Needs to simmer for a while I think to see if I can figure out why the difference.
The reason the member variable MenuItemChosen
isn't documented is that it's an internal variable that wasn't designed to be manipulated by users. Until these new enhancements are added, it's fine to use workarounds like this. Jason's a master of these kinds of solutions (all kinds of solutions actually).
from pysimplegui.
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....
from pysimplegui.
OK! Fixed in 5.0.4.2
ButtonMenu
elements now operate the way that they used to and the same way that MenuBars work. When you get the event for a ButtonMenu element, the values dictionary has the value chosen. After the event is provided, the value the next time an event happens will be None
.
Using @jason990420's excellent sample code, here's it running on 5.0.4.2
pycharm64_xG5WfSu3jJ.mp4
from pysimplegui.
IMO, programmer need to find another way to keep and check the state of each ButtonMenu element.
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!
from pysimplegui.
Related Issues (20)
- Flask click SystemError when used with pySimpleGUI output redirect HOT 1
- [Question] How to trap an event HOT 2
- [Enhancement] CI friendly handling for the first time installation dialog HOT 3
- [Question] How to update class parameter within inherited class HOT 4
- [Question] How To Re-Enter Data For A Specific Field - AND 'CR to act like TAB HOT 1
- [ Bug] sg.ColorChooserButton Unless Additional Tkinter Import HOT 1
- [Bug] Hitting the image-count limit [Fail to create pixmap with Tk_GetPixmap in TkImgPhotoInstanceSetSize] HOT 6
- [Question] Import error HOT 3
- [Question] Change focus highlight when tabbing to button HOT 8
- [ Enhancement/Bug/Question] NOTE - you can also call sg.main() or sg.main_open_github_issue() to post an issue HOT 1
- [ Question] Compiling Errors since License validation HOT 2
- [ Bug] Broken Doc Link HOT 2
- [Question] NOTE - Table get doesn't work HOT 6
- [ Enhancement] allow arrowheads for lines in tkinter graphs HOT 8
- [Question] Question of shortcut HOT 17
- [Question] How to Use PySimpleGui Programs on Other PCs HOT 1
- [ Question] How to detect when we manually enter a value in combo box in Pysimple GUI HOT 1
- [Bug] Table colored rows flashes when updating in 5.0, while they didn't in 4.x HOT 10
- [Question] No right_click_menu in Combo HOT 3
- [Enhancement] Reusing Context Menu HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pysimplegui.