Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Creating Class for Buttons Returns None

    Cinema 4D SDK
    r21 python
    2
    5
    532
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • B
      bentraje
      last edited by

      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"
      
      1 Reply Last reply Reply Quote 0
      • M
        m_adam
        last edited by

        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.

        MAXON SDK Specialist

        Development Blog, MAXON Registered Developer

        1 Reply Last reply Reply Quote 1
        • B
          bentraje
          last edited by

          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. Hehehe

          BTW, 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 well

          Is there a particular reason that you included (object) ?

          1 Reply Last reply Reply Quote 0
          • M
            m_adam
            last edited by

            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.

            MAXON SDK Specialist

            Development Blog, MAXON Registered Developer

            1 Reply Last reply Reply Quote 1
            • B
              bentraje
              last edited by

              @m_adam

              Ah. Gotcha. Thanks for the clarification and link.

              1 Reply Last reply Reply Quote 0
              • First post
                Last post