Giter VIP home page Giter VIP logo

Comments (10)

lilyanne12 avatar lilyanne12 commented on May 28, 2024 2

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.

lilyanne12 avatar lilyanne12 commented on May 28, 2024 1

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.

jason990420 avatar jason990420 commented on May 28, 2024 1

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.

PySimpleGUI avatar PySimpleGUI commented on May 28, 2024 1

Side note for @jason990420 ....image

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.

PySimpleGUI avatar PySimpleGUI commented on May 28, 2024 1

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.

jason990420 avatar jason990420 commented on May 28, 2024

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.

PySimpleGUI avatar PySimpleGUI commented on May 28, 2024

Thank you for the many kind words image 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.

PySimpleGUI avatar PySimpleGUI commented on May 28, 2024

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.

PySimpleGUI avatar PySimpleGUI commented on May 28, 2024

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.

PySimpleGUI avatar PySimpleGUI commented on May 28, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.