Comments (13)
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.
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.
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.
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.
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.
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.
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.
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.
Here's last one solution, maybe best one. And two bugs found in PySimpleGUI.
- Appearance changed
- Variable
menu_def
changed bysg.Menu
Content of variablemenu_def
will be changed after used onsg.Menu
orsg.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.
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.
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.
What are the bugs again... damnit... I know I have them, but want them in front of me again.
from pysimplegui-solution.
Oh, the bugs ABOVE
from pysimplegui-solution.
Just please don't delete any of these Issues of yours!!
They're made from GOLD!
from pysimplegui-solution.
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.
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)
- Click right_click_menu block the event loop
- popup_Animated & multithread
- Binding the ButtonPress an d ButtonRelease for the Button element
- Move mouse pointer by tkinter code
- Change the color for any node in the Tree element
- Scroll item to center of view for Table
- Partial update the data in Table element
- Scroll line to center of view for Multiline
- Build a progressbar by using Graph element
- Renew the row data and columns for the tkinter Treeview widget HOT 1
- Create a new console by Multiline element
- Add SpanSelector to embedded matplotlib canvas for PySimpleGUI
- Multiline text for Checkbox
- Resize window when configured
- Highlight when mouse hover the item in Table/Tree element
- Animation on Canvas element
- Animation GIF by new tcl/tk code HOT 1
- See index in Multiline element
- Filter Table by datetime
- Set colors of scrollbar for Combo Dropdown list
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-solution.