How to return info from a modal dialog ?
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 03/07/2011 at 02:31, xxxxxxxx wrote:
Hi there, I have created a modal dialog and opened it OK.
I know how to use the Command() function to execute code when a gadget is pressed.
But I can't work out how to get information out of the dialogue to use in my CommandData plugin.
Specifically, I need to know what checkboxes the user left checked while in the modal dialog. Now I know the command for this is GetBool(id) and it works inside the Command() function. But Command() doesn't seem to allow any return apart from True/ False.
And if I use GetBool(id) on the instance of MyDialog in the CommandData
plugin, it always returns False, I guess because by then the dialogue is closed.
I can get the information out from inside the Command() function by writing to a global variable from inside the function, but I understand this is a very bad way to do it ?
So I need help to know how to return information from a modal dialog.
Here is a stripped down, minimal example of my code :class MyDialog(gui.GeDialog) :
def CreateLayout(self) :
self.SetTitle("My Dialog")
self.AddCheckbox(10001, c4d.BFH_LEFT,
initw = 85, inith = 10, name = "Checkbox")self.GroupBegin(OK_GROUP, c4d.BFH_CENTER,
cols = 2, title = "OK/ Cancel")self.GroupBorderSpace(5,5,5,5)
self.AddButton(10002, c4d.BFH_LEFT,
initw = 100, inith = 15, name = "OK")self.AddButton(10003, c4d.BFH_RIGHT,
initw = 100, inith = 15, name="Cancel")self.GroupEnd()
return Truedef Command(self, id, msg) :
if id == 10001:
pass
if id == 10002:
self.Close()
if id == 10002:
self.Close()
return Trueclass MyCommandData(plugins.CommandData) :
def Execute(self, doc) :
dialog = MyDialog()
dialog.Open(c4d.DLG_TYPE_MODAL, PLUGIN_ID)
return True -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 03/07/2011 at 03:03, xxxxxxxx wrote:
Just give your dialog a function that returns the result, for instance:
""" Modal Dialog with Result - Example for decade on plugincafe.com licensed under WTFPL. """ import c4d from c4d.gui import GeDialog class MyModal(GeDialog) : ID_TEXT = 10002 ID_BUTTON_OK = 10021 ID_BUTTON_CANCEL = 10022 # symbolscache is not initialised on startup, create FULLFIT later FULLFIT = None def __init__(self, text, okButtonTitle = "OK", cancelButtonTitle = "Cancel") : self.FULLFIT = c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT self.__text = text self.__result = self.ID_BUTTON_CANCEL self.__okbtn = okButtonTitle self.__cncbtn = cancelButtonTitle def CreateLayout(self) : self.AddStaticText(self.ID_TEXT, c4d.BFH_CENTER | c4d.BFV_CENTER, 0, 0, self.__text) self.GroupBegin(1000, self.FULLFIT, cols = 2) self.AddButton(self.ID_BUTTON_OK, self.FULLFIT, 50, 15, name = self.__okbtn) self.AddButton(self.ID_BUTTON_CANCEL, self.FULLFIT, 50, 15, name = self.__cncbtn) self.GroupEnd() return True def Command(self, id, msg) : if id == self.ID_BUTTON_OK: self.__result = self.ID_BUTTON_OK self.Close() elif id == self.ID_BUTTON_CANCEL: self.__result = self.ID_BUTTON_CANCEL self.Close() return True def Open(self) : GeDialog.Open(self, c4d.DLG_TYPE_MODAL) @ property def result(self) : return self.__result def main() : dlg = MyModal("Do you really want to quit ?", "Yes", "No") dlg.Open() print dlg.result if __name__ == "__main__": main()
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 03/07/2011 at 09:22, xxxxxxxx wrote:
Nux.
Is there a reason why you keep using this format: __function__ throughout your code?Most of the time they aren't required. And the code can be written neater like this:
import c4d from c4d import gui GROUP1 =1000 #GROUP1 id TEXTBOX=1001 #TEXTBOX id BUTTON1=1002 #BUTTON1 id BUTTON2=1003 #BUTTON2 id class ExampleDlg(gui.GeDialog) : def CreateLayout(self) : #creat the layout of the dialog self.SetTitle("Simple Dialog") self.GroupBegin(GROUP1, c4d.BFH_SCALEFIT, 3, 1) self.AddEditText(TEXTBOX, c4d.BFH_SCALEFIT) self.AddButton(BUTTON1, c4d.BFH_SCALE, name="MessadeDialog") self.AddButton(BUTTON2, c4d.BFH_SCALE, name="Close") self.GroupEnd() return True def InitValues(self) : #initiate the gadgets with values self.SetString(TEXTBOX, "Hello World!") return True def Command(self, id, msg) : #handles what happens when GUI objects are clicked if id==BUTTON1: gui.MessageDialog(self.GetString(TEXTBOX)) self.SetString(TEXTBOX, "Button was used") elif id==BUTTON2: print "You closed the dialog" self.Close() return True dlg = ExampleDlg() dlg.Open(c4d.DLG_TYPE_MODAL, defaultw=300, defaulth=50)
Is there some benefit to using all of those __whatever__ throught the code?
-ScottA
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 03/07/2011 at 11:21, xxxxxxxx wrote:
Yes, there is. It makes the variables private (Well, not *really* but almost).
But the format is not __variable__. it is __variable. The first is not private.
Sometimes you really don't want that the user can't modify the variables without using a function for it.
I often post examples with some extra stuff some may didn't know so they get some extra information on the fly.GROUP1 =1000 #GROUP1 id TEXTBOX=1001 #TEXTBOX id BUTTON1=1002 #BUTTON1 id BUTTON2=1003 #BUTTON2 id
Do not use global variables. They are unnecessery as well as it makes really sense in this case to make them static variables for the dialog class.
And, most important: Your dialog does not give any result after the dialog was closed.
Cheers,
Niklas -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 03/07/2011 at 11:36, xxxxxxxx wrote:
Thanks Nux, works a treat & allows me to progress with my plugin.
But if you don't mind I have a couple of questions because I don't understand HOW it works.
I don't understand the def __init__, it's not listed as a method under c4d.giu.GeDialog. I've come across it before elsewhere but normally you don't have to handle it at all.
It seems you're creating variables there that are global to the MyModal class ie they can be accessed from inside any of the def in the class. I don't understand why you need to do that rather than list them with your ID constants, right under the class. But I tried it that way and it does seem it doesn't work, you can't update variables you define there.
And what does the double underscore __ signify ?.
Thanks for your helpEdit, cross posted with scott asking some of the same questions.
Also, isn't it OK to leave my constants global ? becuase I want to access them from both the dialog class and the CommandData class, and unnlike my example, my real plugin has a lot of them. I have a python book (not c4d, just python)that says global constants are ok but variables are discouraged ? -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 03/07/2011 at 12:14, xxxxxxxx wrote:
Originally posted by xxxxxxxx
Your dialog does not give any result after the dialog was closed.
Sure it does.
It prints to the console. The same way your code prints to the console when the close function is called.-ScottA
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 04/07/2011 at 03:34, xxxxxxxx wrote:
@Scott: Yea, it prints to the console. But this is not what decade wanted to do.
He wanted get some data after the dialog was closed.@decade:
Originally posted by xxxxxxxx
I don't understand the def __init__,
This is a special method, the Class-constructor. There are more special methods like __del__, __add__, __invert__, __iter__, etc.
See more about it here: linkOriginally posted by xxxxxxxx
becuase I want to access them from both the dialog class and the CommandData class,
This has good reason.
Why should I use global variable if I can avoid them ?
You can access those ID:if dlg.result == MyModal.ID_BUTTON_OK: pass # . . .
if dlg.result == dlg.ID_BUTTON_OK: pass # . . .
I do never create IDs in the global scope. even I'm using a Dialog created with ResEdit. Instead I create a "foo"-class that holds my ID's. This keeps the global - dictionary smaller.
class foo: """ Holds some ID's. """ res = foo() res.EDT_STATIC_TEXT = 10012 # etc ...
If you like the dictionary style the more but you still want to access those IDs via Pointnotation, you can also do this:
class foo: """ Holds some ID's. """ res = foo() res.__dict__ = { "EDT_STATIC_TEXT": 10012, # etc ... } print res.EDT_STATIC_TEXT
I do also never never ever Register my Plugin globally.
1. This is again in global scope
2. It is much more clear codeclass MyObjectData(ObjectData) : PLUGIN_ID = 1002136 ICON = None # We use this as a class - variable to be able to access to it in the plugin, you may need this ? # ... @ staticmethod def Register(cls) : iconPath = join(dirname(__file__), "res", "icon.tif") icon = BaseBitmap() icon.InitWith(iconPath) data = { "id": cls.PLUGIN_ID, "str": "My Object data Plugin", "info": c4d.OBJECT_MODIFIER, "icon": icon, "description": "Omyobject", "g": cls, } if not RegisterObjectPlugin( ** data ) : print "Failed registering Object Plugin" return False else: cls.ICON = icon return True # ... def main() : MyObjectData.Register() if __name__ == "__main__": main()
Originally posted by xxxxxxxx
global constants are ok but variables are discouraged ?
Yea, if you don't want modify the, it's ok, but still not the best way to do.
Accessing global variables is always slower than accessing local ones.
The more outter the variables are, the more time it takes to access them.Cheers,
Niklas -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 04/07/2011 at 08:18, xxxxxxxx wrote:
The reason most people are using globals is because we were taught that way. Even by the most experienced C4D coders.
I once asked about whether using globals was a bad thing on CGTalk. And the answer I got was that they aren't that bad for what we're using them for.
And since I'm new at writing code. And these people were kind enough to help me. I didn't want to disagree with them. So I dropped it.Most of the time globals really aren't going to hurt you for what we're doing in C4D. And everybody seems to be using them. You won't see any noticeable speed differences either, because C4D isn't a game engine.
But this is the problem with using the internet as a learning tool. And learning from other users.
You often get taught how to cheat. Without them telling you that you're cheating. And then all of a sudden you find out one day that you've been doing it ......let's call it.... less than the most optimistic way.If I remember correctly.
I think MAXON even uses globals in their Coffee SDK examples.-ScottA
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 04/07/2011 at 12:41, xxxxxxxx wrote:
Big thanks for the explanations! I will probably take another pass at my code once the functionality is there and think about how to tidy up/ organise it best.