Update Status bar from inside a script



  • On 23/07/2016 at 08:29, xxxxxxxx wrote:

    How can I update the status bar with c4d.StatusSetBar() and make it show the progress from inside a script?
    Even if I place c4d.EventAdd() commands inside my loop, the status bar doesn't update.



  • On 23/07/2016 at 10:32, xxxxxxxx wrote:

    You need to make your computer stop processing the script per iteration for a short period of time to see the value change take place using sleep().

    import c4d, time  
    def main() :  
      
      for i in xrange(0, 101) :  
      
          #Convert the value to a string. And add the percent symbol to it  
          value = str(i)  
          value += "%"                    
          c4d.StatusSetText( value )  
            
          time.sleep(.10)  
      
    if __name__=='__main__':  
      main()
    


  • On 23/07/2016 at 15:43, xxxxxxxx wrote:

    It is still not working
    Could it be that it is because I also have a dialog?
    However, the main loop is after the Command method of the dialog closes the dialog (and, yet, the closing only really happens after the main loop finishes, don't really understand why).
    This is, in a nutshell, my main loop:

      
    lim=len(all_files)   
    count=100.0/lim   
      
    for c,i in enumerate(all_files) :   
                   
        # perform some stuff with the filename, inside the all_files list   
        # copy and erase some files, based on the processed filename   
      
        # only update the status every 100 items   
        if c % 100 == 0:   
            c4d.StatusSetBar(int(c*count))   
            c4d.StatusSetText("%s / %s" % (c,lim))   
            time.sleep(.1)   
                     
    c4d.StatusClear()   
    


  • On 24/07/2016 at 07:26, xxxxxxxx wrote:

    I have already tried:

      
    c4d.EventAdd(c4d.EVENT_FORCEREDRAW)   
    

    and

      
    c4d.SendCoreMessage(c4d.COREMSG_CINEMA,c4d.BaseContainer(c4d.COREMSG_CINEMA_FORCE_AM_UPDATE))   
    

    All of it with a time.sleep(.25) in front... and nothing!!
    I still get no refresh in the status bar.
    I really would like to get some feedback to the user in the status bar, as the process can take a few seconds to finish.



  • On 24/07/2016 at 09:47, xxxxxxxx wrote:

    I don't know about anyone else. But I'm not totally clear on what you're doing.
    It sounds like you're having threading issues. But it's not clear to me.
    Is there any way you can post a simple working example?
    Something that runs, has a GeDialog in it, and your progress bar code in it.

    FYI:
    I've noticed that the support guys don't usually answer questions on the weekends anymore like they used to.
    They seem to be sticking to regular business hours now. Which is understandable.
    So if you ask a question on Friday. It can take up to 3 days to get a reply from them.

    -ScottA



  • On 24/07/2016 at 10:41, xxxxxxxx wrote:

    I totally understand that and I know that if I post a question on Friday, I may only get and answer on Monday. So, I appreciate very much your help during these weekend days.

    I'm writing a script. It is not a full plugin. So, I just have a GeDialog to define the parameters but my code, the one that should update the progress bar, is outside of the code of the dialog.
    So, in my main I have this:

      
    dlg=my_dialog()   
    dlg.Open(c4d.DLG_TYPE_MODAL, defaultw=300, defaulth=50)   
    the_path=dlg.the_path   
    the_name=dlg.the_name   
           
    if not dlg.ok: return   
    

    I have some variables inside the dialog class (the_path, the_name and ok).
    If ok is True, the user pressed the OK button.
    If ok is False, the user pressed the Cancel button.
    This is all set in the Command method.
    So, the code that follows the last line of code above is the one, inside the main that should update the progress bar.
    A strange thing that occurs is that my Command method includes this:

      
    def Command(self,id, msg) :   
      
        if id==B_CANCEL:   
            self.ok=False   
            self.Close()   
            return True   
      
        if id==B_OK:               
            self.ok=True   
            self.Close()   
            return True   
    

    ...and the dialog closes if I press the Cancel button.
    But if I press the OK button, the dialog only closes after my whole main loop finishes. And that is already outside the dialog code.
    Very weird.



  • On 24/07/2016 at 11:45, xxxxxxxx wrote:

    I'm afraid I'm still not clear on the problem.
    Here is an example that implements the progressbar in two different places.
    One is in the GeDialog's Command() method. The other one is executed in the main() method.
    They are both working as expected for me.

    import c4d, time  
    from c4d import gui  
      
    class MyDialog(gui.GeDialog) :  
      
      BUTTON_ID = 1001  
        
      def CreateLayout(self) :  
          self.AddButton(self.BUTTON_ID, c4d.BFH_SCALE|c4d.BFV_SCALE, 100, 25, "Close Dialog")   
          return True  
      
      def InitValues(self) :          
          return True  
      
      def Command(self, id, msg) :  
            
          if id == self.BUTTON_ID:  
                
              #If you use this code  
              #The progressbar will update. Then the dialog will close when it's finished  
                
              """for i in xrange(0, 101) :  
      
                  #Convert the value to a string. And add the percent symbol to it  
                  value = str(i)  
                  value += "%"                    
                  c4d.StatusSetText( value )  
            
                  time.sleep(.10)"""    
                    
              c4d.StatusClear()            
                
              #Closes the dialog after the above code runs  
              self.Close()  
                
          return True  
      
    if __name__=='__main__':  
      dlg = MyDialog()  
      dlg.Open(dlgtype=c4d.DLG_TYPE_MODAL, defaultw=200, defaulth=200)  
        
      #If you use code  
      #The dialog will close first. Then the progressbar will update  
      """for i in xrange(0, 101) :  
          #Convert the value to a string. And add the percent symbol to it  
          value = str(i)  
          value += "%"  
          c4d.StatusSetText( value )          
          time.sleep(.10)  
            
      c4d.StatusClear()"""
    

    The only thing I can think of is to maybe try not using True after each button code. Just call True once at the end of the Command() method. But I doubt that would make a difference.
    Sorry. I'm not being much help.

    -ScottA



  • On 24/07/2016 at 12:02, xxxxxxxx wrote:

    Well, I tried it, and... it doesn't work
    I created a simple movie showing you what is happening:

    https://youtu.be/qmtCDCILCAs



  • On 24/07/2016 at 12:27, xxxxxxxx wrote:

    It's works fine for me on a PC. You're using a mac right?
    In the past I've had several mac users tell me that my dialog.Close() code did not work for them.
    I don't own one so I can't test it. But based on my experiences, macs definitely have problem with the dialog.Close() function.

    -ScottA



  • On 24/07/2016 at 14:30, xxxxxxxx wrote:

    Thank you, Scott.
    So, it is a Mac issue
    Well, my code works, except for that problem.
    I will try to find a workaround for it.
    Damn!!! It should work fine on both platforms.



  • On 25/07/2016 at 02:21, xxxxxxxx wrote:

    Hello,

    the following script works for me on both win and mac (R17 SP2) :

      
    class TestDialog(gui.GeDialog) :  
       
      def CreateLayout(self) :  
      
          self.SetTitle("test")  
            
          self.AddButton(1000, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 0, 0, "Action")  
          self.AddButton(2000, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 0, 0, "Close")  
      
          return True  
      
      def Command(self, id, msg) :  
      
          if id == 1000:  
              for i in xrange(100) :  
                  time.sleep(.1)  
                  print(i)  
                  c4d.StatusSetBar(float(i))  
                    
              c4d.StatusSetBar(float(-1))  
      
          if id == 2000:  
              self.Close()  
                
          return c4d.gui.GeDialog.Command(self, id, msg)   
      
    def main() :  
      dialog = TestDialog()  
        
      dialog.Open(c4d.DLG_TYPE_MODAL_RESIZEABLE, 132456, -1 ,-1 ,400 ,400)  
      
    if __name__=='__main__':  
      main()  
    

    I think there are some differences on both Mac and Windows in regards to GUI handling so I cannot guarantee that this works in any situation.

    Best wishes,
    Sebastian



  • On 25/07/2016 at 02:54, xxxxxxxx wrote:

    I will try it as soon as I get home.
    I'm at work now and I only have access to Windows machines.
    Thank you, Sebastian.



  • On 26/07/2016 at 00:05, xxxxxxxx wrote:

    Hello again, Sebastian.
    I tried it and no Status Bar appears :-(
    And the Console output is only shown in the end of the cycle.
    So, no updates during the cycle.


Log in to reply