Creating Class for Buttons Returns None
-
Hi,
Usually, I create buttons by just adding the vanilla lines. I wanted to create a class for buttons but it returns None and gives and me an error of
line 34, in create bmp_btn.SetImage(bmp_color, True) AttributeError: 'NoneType' object has no attribute 'SetImage'
Interestingly. The same code works on a vanilla code. So I was thinking there is an additional procedure when creating a class?
You can check the working code here:
import c4d from c4d import bitmaps, documents, gui, plugins, threading, utils PLUGIN_ID = 18113289 class ColorButton(c4d.gui.GeDialog): def __init__(self): self.width = None self.height = None self.color = None self.color = None self.btn_id = 3000 def create(self, w, h, color,btn_id): self.width = w self.height = h self.color = color bmp_color = c4d.bitmaps.BaseBitmap() bmp_color.Init(w, h) for y in xrange(w): for x in xrange(h): bmp_color.SetPixel(x, y, color[0], color[1], color[2]) bcBitmapButton = c4d.BaseContainer() bcBitmapButton[c4d.BITMAPBUTTON_BUTTON] = True bmp_btn = self.AddCustomGui(btn_id, c4d.CUSTOMGUI_BITMAPBUTTON, "", c4d.BFH_CENTER|c4d.BFV_CENTER, w, h, bcBitmapButton) bmp_btn.SetImage(bmp_color, True) class MyDialog(c4d.gui.GeDialog): buttonId = 2000 def CreateLayout(self): self.SetTitle('Class Button') # Creating a red button through vanilla lines w = 50 h = 50 color=(255,0,0) btn_id = 5000 bmp_color = c4d.bitmaps.BaseBitmap() bmp_color.Init(w, h) for y in xrange(w): for x in xrange(h): bmp_color.SetPixel(x, y, color[0], color[1], color[2]) bcBitmapButton = c4d.BaseContainer() bcBitmapButton[c4d.BITMAPBUTTON_BUTTON] = True bmp_btn = self.AddCustomGui(btn_id, c4d.CUSTOMGUI_BITMAPBUTTON, "", c4d.BFH_CENTER|c4d.BFV_CENTER, w, h, bcBitmapButton) bmp_btn.SetImage(bmp_color, True) # Creating a red button through class # This part causes the error red_button = ColorButton() red_button.create(w=50,h=50,color=(255,0,0),btn_id=6000) return True def Command(self, id, msg): return True def CoreMessage(self, id, data): return True class MyMenuPlugin(plugins.CommandData): dialog = None def Execute(self, doc): # create the dialog if self.dialog is None: self.dialog = MyDialog() return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaultw=200, defaulth=150, xpos=-1, ypos=-1) def RestoreLayout(self, sec_ref): # manage the dialog if self.dialog is None: self.dialog = MyDialog() return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref) if __name__ == "__main__": okyn = plugins.RegisterCommandPlugin(PLUGIN_ID, "Class Button",0, None, "Class Button", MyMenuPlugin()) if (okyn): print "Class Button"
-
Hi @bentraje,
the main issue is that ColorButton is another GeDialog, so that means if you want to draw something you have to open it first.
Either you have to change it to a SubDialog, this way you can embed it within another GeDialog/SubDialog see gedialog_subdialog_r19.py .
Or either you have to use the instance of the dialog that is already open to do the draw operation.import c4d class ColorButton(object): def __init__(self): self.width = None self.height = None self.color = None self.color = None self.btn_id = 3000 def create(self, dlg, w, h, color, btn_id): self.width = w self.height = h self.color = color bmp_color = c4d.bitmaps.BaseBitmap() bmp_color.Init(w, h) for y in xrange(w): for x in xrange(h): bmp_color.SetPixel(x, y, color[0], color[1], color[2]) bcBitmapButton = c4d.BaseContainer() bcBitmapButton[c4d.BITMAPBUTTON_BUTTON] = True bmp_btn = dlg.AddCustomGui(btn_id, c4d.CUSTOMGUI_BITMAPBUTTON, "", c4d.BFH_CENTER | c4d.BFV_CENTER, w, h, bcBitmapButton) bmp_btn.SetImage(bmp_color, True) class MyDialog(c4d.gui.GeDialog): def CreateLayout(self): # Creating a red button through class # This part causes the error red_button = ColorButton() red_button.create(self, w=50,h=50,color=(255,0,0), btn_id=6000) return True
Now regarding which solution is best, it is up to you, but I will argue that SubDialog is cleaner since Gadget ID become local to this SubDialog, while if you share an instance of the GeDialog, you have to be sure that all ID is unique.
Hope it makes sense,
Cheers,
Maxime. -
Thanks for the response. The code works as expected.
For the option, I think I'll go with "use the instance of the dialog" like in your code above. Seems like an easier way to handle and maintain.With the
AutoID()
class you shared, I never had any problem with the ID management now. HeheheBTW, just one thing, in your code you wrote
class ColorButton(object):
. which makes it that you are inheriting a class, correct me if I'm wrong.However, it seems like the
class ColorButton:
seems to work as wellIs there a particular reason that you included
(object)
? -
https://stackoverflow.com/questions/4015417/python-class-inherits-object
It's just a "good practice" for python 2.X to always derive from object your BaseClass.Cheers,
Maxime. -
Ah. Gotcha. Thanks for the clarification and link.