How to Get checked/unchecked state of menu item?
-
Hi,
Use MenuInitString() change checked/unchecked state of menu item,
how to get checked/unchecked state?
Thanks for any help! -
Hello @chuanzhen,
Thank you for reaching out to us. There is no mechanism to get the state of a menu item as they are not meant to be the data layer of your app. You must store and track these values yourself; properties are a good pattern to solve such things, as you can encapsulate the GUI-DATA bindings in a very clean way with them. See end of my posting for a small example.
Cheers,
FerdinandAn example output:
MY_DIALOG.IsFiles = False MY_DIALOG.IsFolders = False self._isFiles = True self._isFolders = True self._isFiles = False self._isFolders = False self._isFiles = True
The code:
"""Provides a simple example for handling checkable menu items and their state with properties inside a GeDialog instance. """ import c4d class MyDialog (c4d.gui.GeDialog): """Implements a dialog which encapsulates menu item states in properties. """ ID_MENU_DATA_FILES: int = 1000 # The ID for the "Files" menu item. ID_MENU_DATA_FOLDERS: int = 1001 # The ID for the "Folders" menu item. def __init__(self) -> None: """Initializes the dialog. """ self._isFiles: bool = False # The internal field for the IsFiles property. self._isFolders: bool = False # The internal field for the IsFolders property. super().__init__() def CreateLayout(self) -> bool: """Called by Cinema 4D to populate the dialog with gadgets. """ # We build a very simply menu with the structure: # Data # +-- Files # +-- Folders self.MenuSubBegin("Data") self.MenuAddString(MyDialog.ID_MENU_DATA_FILES, "Files") self.MenuAddString(MyDialog.ID_MENU_DATA_FOLDERS, "Folders") self.MenuSubEnd() self.MenuFinished() return super().CreateLayout() def Command(self, cid: int, data: c4d.BaseContainer) -> bool: """Called by Cinema 4D when a gadget, including menus, has been invoked. """ # When one of the menu items has been invoked, we simply toggle the matching property. if cid == MyDialog.ID_MENU_DATA_FILES: self.IsFiles = not self.IsFiles if cid == MyDialog.ID_MENU_DATA_FOLDERS: self.IsFolders = not self.IsFolders return super().Command(cid, data) # --- The menu items realized as properties ---------------------------------------------------- @property def IsFiles(self) -> bool: """Gets the "Files" state. We just get the value from the private field. """ return self._isFiles @IsFiles.setter def IsFiles(self, value: bool) -> None: """Sets the "Files" state. The setter also updates the GUI via GeDialog.MenuInitString, making sure that the properties are always correctly reflected. In this case we also print out the new value to demonstrate how the dialog works. """ if not isinstance(value, bool): raise TypeError(value) if self._isFiles == value: return self._isFiles = value self.MenuInitString(MyDialog.ID_MENU_DATA_FILES, enabled=True, value=self._isFiles) print (f"{self._isFiles = }") @property def IsFolders(self) -> bool: """Gets the "Folders" state. """ return self._isFolders @IsFolders.setter def IsFolders(self, value: bool) -> None: """Sets the "Folders" state. """ if not isinstance(value, bool): raise TypeError(value) if self._isFolders == value: return self._isFolders = value self.MenuInitString(MyDialog.ID_MENU_DATA_FOLDERS, enabled=True, value=self._isFolders) print (f"{self._isFolders = }") # Attribute deceleration for a MyDialog instance used by main(). MY_DIALOG: MyDialog def main(): """Runs the example. """ # We are using here the global attribute hack to make the dialog work in async mode in a Script # Manager script. Please do not use this hack in a production environment, Script Manger scripts # should not open async dialogs, they are restricted to plugins as they can properly manage the # lifetime of the dialog. global MY_DIALOG MY_DIALOG = MyDialog() # Open the dialog in asynchronous mode. MY_DIALOG.Open(c4d.DLG_TYPE_ASYNC, defaultw=200, defaulth=100) # We can now either directly read and write the properties of the dialog ... print (f"\n{MY_DIALOG.IsFiles = }") print (f"{MY_DIALOG.IsFolders = }\n") MY_DIALOG.IsFiles = True # or interact via GeDialog.Command with the dialog to toggle the properties and their GUI. MY_DIALOG.Command(MY_DIALOG.ID_MENU_DATA_FOLDERS, c4d.BaseContainer()) if __name__ == "__main__": main()
-
@ferdinand Thanks!