Giter Club home page Giter Club logo

Comments (13)

jason990420 avatar jason990420 commented on August 16, 2024 1

Of course, share my code with you is best thing, you enjoy and I enjoy !
You may need to care about those two mentioned bugs.

from pysimplegui-solution.

jason990420 avatar jason990420 commented on August 16, 2024

So it is only work for sg.Menu and sg.buttonMenu becuase they have method to update menu_definition ?
Where I can find the definition of menu_definition ?

from pysimplegui-solution.

jason990420 avatar jason990420 commented on August 16, 2024

I don't know issue here can be opened by others ? I though only I can post something here., even no comment ....

from pysimplegui-solution.

jason990420 avatar jason990420 commented on August 16, 2024

Two different menu_def get the same result,

menu_def = [['&File', ['&Open     Ctrl-O', '&Save       Ctrl-S', '&Properties', 'E&xit']],
            ['&Edit', [['Special', 'Normal',['Normal1', 'Normal2'], 'Undo']], ],
            ['&Toolbar', ['---', 'Command &1::Command_Key', 'Command &2', '---', 'Command &3', 'Command &4']],
            ['&Help', ['&About...']], ]
menu_def = [['&File', ['&Open     Ctrl-O', '&Save       Ctrl-S', '&Properties', 'E&xit']],
            ['&Edit', ['Special', 'Normal',['Normal1', 'Normal2'], 'Undo'], ],    # Different Line here
            ['&Toolbar', ['---', 'Command &1::Command_Key', 'Command &2', '---', 'Command &3', 'Command &4']],
            ['&Help', ['&About...']], ]

from pysimplegui-solution.

PySimpleGUI avatar PySimpleGUI commented on August 16, 2024

The problem people tell me are "I want to disable a specific item"

That kind of easy operation is what they can't seem to figure out. It's basic, really basic, list manipulation code.

from pysimplegui-solution.

jason990420 avatar jason990420 commented on August 16, 2024

Here's tree structure for menu_def, I got a "bug" here ? sg.Combo after update values and set_to_index, input field will keep old highlight length.

image

import PySimpleGUI as sg


class Menu():

    tree_dict = {}

    class Node():

        def __init__(self, parent, key, value):
            self.parent = parent
            self.key = key
            self.value = value
            self.children = []

    def __init__(self, menu_def):
        Menu.tree_dict[''] = self.Node('', '', 'root')
        self.menu(menu_def)

    def menu(self, menu_def):
        def sub_menu(menu_def, parent=''):
            key = None
            for item in menu_def:
                if isinstance(item, str):
                    key = self.insert(parent, item)
                elif isinstance(item, (list, tuple)):
                    if key is None:
                        key = self.insert(parent, None)
                    sub_menu(item, parent=key)

        for main_item in menu_def:
            sub_menu(main_item, parent='')

    def insert(self, parent, value):
        if parent in Menu.tree_dict:
            key  = self.new_key()
            node = self.Node(parent, key, value)
            Menu.tree_dict[parent].children.append(key)
            Menu.tree_dict[key] = node
            return key

    def new_key(self):
        i = 1
        while str(i) in Menu.tree_dict:
            i += 1
        return str(i)

    @property
    def menu_def(self):
        def sub_menu(parent):
            row = []
            for child in Menu.tree_dict[parent].children:
                node = Menu.tree_dict[child]
                if node.value is None:
                    child = node.key
                else:
                    row.append(node.value)
                if node.children:
                    row.append(sub_menu(child))
            return row
        result = []
        for child in Menu.tree_dict[''].children:
            node = Menu.tree_dict[child]
            child = node.key
            row = [node.value]
            if node.children:
                row.append(sub_menu(child))
            result.append(row)
        return result

    def enable(self, item):
        if item in ("", None, "---"):
            return
        for node in Menu.tree_dict.values():
            if node.value.strip() == item.strip():
                if item[0] == "!":
                    node.value = node.value[1:]
                return

    def disable(self, item):
        if item in ("", None, "---"):
            return
        for node in Menu.tree_dict.values():
            if node.value.strip() == item.strip():
                if item[0] != "!":
                    node.value = "!" + node.value
                return

    def __repr__(self, root='', tab=1):
        node = Menu.tree_dict[root]
        string = str(node.value)
        for key in node.children:
            string += '\n'+'    '*tab+self.__repr__(root=key, tab=tab+1)
        return string

def get_list(menu):
    return [item.strip() for item in str(menu).split('\n')
        if item.strip() not in ('root', '---', '')]

menu_def = [['&File', ['&Open     Ctrl-O', '&Save       Ctrl-S', '&Properties', 'E&xit']],
            ['&Edit', ['Special', 'Normal',['Normal1', 'Normal2'], 'Undo'], ],
            ['&Toolbar', ['---', 'Command &1::Command_Key', 'Command &2', '---', 'Command &3', 'Command &4']],
            ['&Help', ['&About...']], ]

menu = Menu(menu_def)

sg.theme("DarkBlue")
sg.set_options(font=('Courier New', 16))

item_list = get_list(menu)
layout = [
    [sg.Menu(menu_def, key='Menu')],
    [sg.Combo(item_list, size=(40, 1), auto_size_text=True, key='Combo')],
    [sg.Button("Disable"), sg.Button("Enable")],
]
window = sg.Window("Title", layout, finalize=True)

while True:
    event, values = window.read()
    if event == sg.WINDOW_CLOSED:
        break
    elif event == 'Enable':
        select = values['Combo']
        if select not in item_list:
            continue
        index = item_list.index(select)
        menu.enable(select)
        window['Menu'].update(menu_definition=menu.menu_def)
        item_list = get_list(menu)
        window['Combo'].update(values=item_list, set_to_index=index)
    elif event == 'Disable':
        select = values['Combo']
        if select not in item_list:
            continue
        index = item_list.index(select)
        menu.disable(select)
        window['Menu'].update(menu_definition=menu.menu_def)
        item_list = get_list(menu)
        window['Combo'].update(values=item_list, set_to_index=index)

    print(event, values)

window.close()

Another easy way is to convert list to str, then replace the string directly, But have to care the string format.
image

import PySimpleGUI as sg

class Menu():

    """
   When item used in enable or  disable function,  full string required and same delimiter of string in menu definition
    like "'Command &1::Command_Key'", exactly same as they are in menu_def.
    """
    def __init__(self, menu_def):
        self.menu = str(menu_def)

    def enable(self, item):
        item = eval(item)
        if ((not isinstance(item, str)) or (item == "") or
                (item not in self.menu) or (item[0]!="!")):
            return False
        self.menu = self.menu.replace(repr(item), repr(item[1:]))

    def disable(self, item):
        item = eval(item)
        if ((not isinstance(item, str)) or (item == "") or
                (item not in self.menu) or (item[0]=="!")):
            return False
        self.menu = self.menu.replace(repr(item), repr("!"+item))

    @property
    def menu_def(self):
        return eval(self.menu)

menu_def = [['&File', ['&Open     Ctrl-O', '&Save       Ctrl-S', '&Properties', 'E&xit']],
            ['&Edit', ['Special', 'Normal',['Normal1', 'Normal2'], 'Undo'], ],
            ['&Toolbar', ['---', 'Command &1::Command_Key', 'Command &2', '---', 'Command &3', 'Command &4']],
            ['&Help', ['&About...']], ]

menu = Menu(menu_def)

sg.theme("DarkBlue")
sg.set_options(font=('Courier New', 16))

layout = [
    [sg.Menu(menu_def, key='Menu')],
    [sg.Button("Disable"), sg.Button("Enable")],
]
window = sg.Window("Title", layout, finalize=True)
enable = "'&Toolbar'"
disable = "'!&Toolbar'"
while True:
    event, values = window.read()
    if event == sg.WINDOW_CLOSED:
        break
    elif event == 'Enable':
        menu.enable(disable)
        window['Menu'].update(menu_definition=menu.menu_def)
    elif event == 'Disable':
        menu.disable(enable)
        window['Menu'].update(menu_definition=menu.menu_def)

    print(event, values)

window.close()

Both cases update full menu definition, there's no baritem saved, so cannot disable or enable them directly by

baritem.entryconfigure(state="disabled")    # or "normal"

All menu_item can be found by

def all_children(wid) :
    _list = wid.winfo_children()
    for item in _list :
        if item.winfo_children() :
            _list.extend(item.winfo_children())
    return [wid] + _list

widget_list = all_children(window['MENU'].Widget)    # Called when window finalized

from pysimplegui-solution.

jason990420 avatar jason990420 commented on August 16, 2024

Here's last one solution, maybe best one. And two bugs found in PySimpleGUI.

  1. Appearance changed

Before menu_def update
image

After menu_def updated
image

  1. Variable menu_def changed by sg.Menu
    Content of variable menu_def will be changed after used on sg.Menu or sg.Menu.update.

Before window finalized

[['&File', ['&Open     Ctrl-O', '&Save       Ctrl-S', '&Properties', 'E&xit']], ['&Edit', [['Special', 'Normal', ['Normal1', 'Normal2']], 'Undo']], ['&Toolbar', ['---', 'Command &1::Command_Key', 'Command &2', '---', 'Command &3', 'Command &4']], ['&Help', ['&About...']]]

After window finalized

[['File', ['&Open     Ctrl-O', '&Save       Ctrl-S', '&Properties', 'E&xit']], ['Edit', [['Special', 'Normal', ['Normal1', 'Normal2']], 'Undo']], ['Toolbar', ['---', 'Command &1::Command_Key', 'Command &2', '---', 'Command &3', 'Command &4']], ['Help', ['&About...']]]

Demo code.

image

from copy import deepcopy
import PySimpleGUI as sg

class Menu(sg.Menu):

    def __new__(cls, menu_def, **kwargs):
        """
        To define Guage same as sg.Graph
        """
        return sg.Menu.__new__(cls)

    def __init__(self, menu_def, **kwargs):
        self.def_ = deepcopy(menu_def)
        super().__init__(menu_def, **kwargs)

    def replace(self, menu_def, old, new):
        for i, item in enumerate(menu_def):
            if isinstance(item, str):
                if item == old:
                    menu_def[i] = new
                    return True
            else:
                if self.replace(item, old, new):
                    return True
        return False

    def enable(self, item):
        if item[0] == "!" and self.replace(self.def_, item, item[1:]):
            self.update(menu_definition=deepcopy(self.def_))

    def disable(self, item):
        if item[0] != "!" and self.replace(self.def_, item, "!"+item):
            self.update(menu_definition=deepcopy(self.def_))

menu_def = [['&File', ['&Open     Ctrl-O', '&Save       Ctrl-S', '&Properties', 'E&xit']],
            ['&Edit', [['Special', 'Normal',['Normal1', 'Normal2'] ], 'Undo'], ],
            ['&Toolbar', ['---', 'Command &1::Command_Key', 'Command &2', '---', 'Command &3', 'Command &4']],
            ['&Help', ['&About...']], ]

sg.theme("DarkBlue")
sg.set_options(font=('Courier New', 16))

menu_def = [['&File', ['&Open     Ctrl-O', '&Save       Ctrl-S', '&Properties', 'E&xit']],
            ['&Edit', [['Special', 'Normal',['Normal1', 'Normal2'] ], 'Undo'], ],
            ['&Toolbar', ['---', 'Command &1::Command_Key', 'Command &2', '---', 'Command &3', 'Command &4']],
            ['&Help', ['&About...']], ]

item_list = ['&File', '&Open     Ctrl-O', '&Save       Ctrl-S', '&Properties',
    'E&xit', '&Edit', 'Special', 'Normal', 'Normal1', 'Normal2', 'Undo',
    '&Toolbar', 'Command &1::Command_Key', 'Command &2', 'Command &3',
    'Command &4', '&Help', '&About...']

layout = [
    [Menu(menu_def, key='MENU')],
    [sg.Button('Enable'), sg.Button('Disable')],
    [sg.Combo(item_list, default_value='&File', size=(25, 1), readonly=True,
        key='Combo')],
]
window = sg.Window("Title", layout, finalize=True)
menu = window['MENU']

while True:
    event, values = window.read()
    if event == sg.WINDOW_CLOSED:
        break
    item = values['Combo']
    if event == 'Enable':
        item = item if item[0] == '!' else '!'+item
        menu.enable(item)
    elif event == 'Disable':
        item = item if item[0] != '!' else item[1:]
        menu.disable(item)

window.close()

from pysimplegui-solution.

PySimpleGUI avatar PySimpleGUI commented on August 16, 2024

Can I pull this new Menu class into the PySimpleGUI code??

This is what I would like. I expected functions, but you've actually provided MUCH better way to do it.

The one thing I really want to avoid ever seeing in user code, except for the Gauge and other advanced user-defined-elements, is the word "class". It appears that what you've wrote I can copy into PySimpleGUI.py :-)

Please let me know if I'm understanding your solution correctly. I would appear that is what you've made... .something meant for me more than the user in terms of the class.

You are SUCH an advanced programmer. I can't keep up with a lot of what you write.

from pysimplegui-solution.

PySimpleGUI avatar PySimpleGUI commented on August 16, 2024

What are the bugs again... damnit... I know I have them, but want them in front of me again.

from pysimplegui-solution.

PySimpleGUI avatar PySimpleGUI commented on August 16, 2024

Oh, the bugs ABOVE

from pysimplegui-solution.

PySimpleGUI avatar PySimpleGUI commented on August 16, 2024

Just please don't delete any of these Issues of yours!!

They're made from GOLD!

from pysimplegui-solution.

PySimpleGUI avatar PySimpleGUI commented on August 16, 2024

I must have changed the code to do the color setting of menus only in the function that builds the menu initially and didn't apply that code in the update method. That's the only thing I can think of that would cause the change. I am getting a brand new tk.Menu in the update so it would need to be built the same as I did initially.

from pysimplegui-solution.

PySimpleGUI avatar PySimpleGUI commented on August 16, 2024

The Combo one I've not seen. I did run into odd behavior while recording the Input element lesson the other day. The element has to have the focus for some of the operations to work correctly. Not sure if something similar may be happening on the Combo but wouldn't surprise me because a combo is a combination of input and a drop-down.

from pysimplegui-solution.

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.