Guido cannot work in python mode

I translated guido exmple into python mode,but it cannot work,thanks for help

add_library('Guido')

def setup ():
    global slider
    size(400, 400);
     
    Interactive.make( this )
       
    slider =  Slider( 2, 2, width-4, 16 )


def draw ():
    global slider
    background( 0 );
    
    fill( 255 - (slider.value * 255) )
    ellipse( width/2, height/2, 150, 150 )
    fill( slider.value * 255 )
    ellipse( width/2, height/2, 70, 70 )


class Slider():


    
    def __init__ ( self, xx,  yy,  ww,  hh ) :
        
        self.x = xx
        self.y = yy
        self.width = ww
        self.height = hh
        
        self.valueX = self.x
        self.value=0

        Interactive.add( this )
    
    

    def mouseDragged (self,  mx,  my ):
    
        self.valueX = mx - height/2;
        
        if ( self.valueX < self.x ):
            self.valueX = self.x
        if ( self.valueX > self.x+self.width-self.height ):
            self.valueX = self.x+self.width-self.height
        
        self.value = self.map( self.valueX, self.x, self.x+self.width-self.height, 0, 1 );
    

    def draw (self): 
    
        noStroke()
        
        fill( 100 )
        rect(self.x, self.y, self.width, self.height)
        
        fill( 120 );
        rect( self.valueX, self.y, slef.height, self.height )
1 Like

Do you have the library installed? Did you get it from Contributions Manager, or from https://github.com/fjenett/Guido ?

Does the example work for you in Java mode? In python mode, are you getting error messages? What happens?

Not all Java libraries are compatible with Python mode, although some can be made to work or worked-around…

1 Like

thanks.I have installed the Guido,and it can work in JAVA mode.there is no error in python mode ,you can paste the code to the processing and run it .I thought python mode run on jython , it should work well just as on java

For some java libraries I believe that it is an interface issue – libraries that modify fields ( and some forms of callbacks and reflection, I think?) aren’t correctly exposed from jython to the mode due to the architecture. See the FAQ for some discussion.

Some libraries such as Ani require you to specify a variable name for animation. Unfortunately they cannot access Python variables directly (and Java’s built in classes are immutable). To solve this problem we instead create a mutable PrimitiveFloat object. This object has a field .value , which you can use for these purposes. GitHub - jdf/processing.py: Write Processing sketches in Python

and the wiki

Some libraries–those that depend on certain functions being defined in your sketch–will not work. As we become aware of those, we will try to work with the authors of those libraries to make the design compatible with Python Mode, or at least to provide workarounds. GitHub - jdf/processing.py: Write Processing sketches in Python

1 Like

For such libraries, see whether they offer an alternative way to pass a custom callback (generally an instance of some functional interface provided by the library) besides those callbacks directly defined in the PApplet sketch. :smirk_cat:

1 Like

Please file a bug at https://github.com/jdf/Processing.py-Bugs/issues/new

1 Like

It’d be gr8 if we could also see the original Java Mode runnable version. :see_no_evil:

As a general advice, any conversion attempts become much more achievable when both the original & attempt codes are posted together. :smile_cat:

I checked the Guido GitHub repo. It includes some python-mode examples, but these don’t seem to work either.

If you’re simply looking for a GUI library with decent Processing.py support, you may want to try ControlP5. If you’re interested, I’ve written a tutorial on using ControlP5.

Looking at the commit dates, an issue might be that Guido (and the examples) are for PDE 2.x and/or an earlier version of Python mode. So one thing you could try is running Guido and those examples with a Python mode release from 2014…

After some gander at Guido repo, seems like all of its Python examples and workarounds had never been released nor tagged for years! :date:

All the Python Mode examples linked by @tabreturn: :star_struck:

Relies on an Interactive.make() overloaded signature w/ 2 args: Interactive.make(this, True): :flushed:

However, that overloaded static method version exists on ‘master’ only, nowhere else! :open_mouth:

So even today, only the Interactive.make() w/ 1 parameter is available. :expressionless:

However, w/o it, we have to close Python Mode completely before each re-run! :scream:

But fret not! Now that Python Mode allows directly access to any Java member, regardless its access permission, we can simply assign None to Interactive.manager before calling Interactive.make(): :crazy_face:

# Workaround for missing overloaded Interactive.make(PApplet, boolean):
print Interactive.manager
Interactive.manager = None 
Interactive.make(this)

It forces Interactive.make() to always instantiate a new Interactive rather than reusing an existing 1, which is unfortunately buggy on Python Mode. :bug:

There are more problems when using Guido on Python Mode though. :zipper_mouth_face:
Interactive.add() doesn’t work on Python classes. :snake:
Instead, we need to create a class which inherits from ActiveElement: :face_with_monocle:

# ActiveElement inheritance replaces Interactive.add(Object):
class SimpleButton(ActiveElement):

W8! There’s 1 more bug! Which was fixed on ‘master’, but it’s unavailable for us: :face_with_head_bandage:

Callback ActiveElement::mousePressed() is invoked 2 times! :calling:

  • 1st as signature ActiveElement::mousePressed() w/ no parameters.
  • 2nd as signature ActiveElement::mousePressed(float, float), which receives mouse’s current coordinates.

As you can see, all empty callbacks were commented on ‘master’ version. :see_no_evil:
But they’re very active on the distributed version we use currently. :space_invader:

Java, due to its native overloading dispatch, can pick which 1 to use. :coffee:
But in Python, we’ve gotta def a callback which accepts all overloaded signatures coming at it! :grimacing:

# *args for both signatures ActiveElement::mousePressed() &
# ActiveElement::mousePressed(float, float):
def mousePressed(self, *args):

And b/c it’s called back twice, we need to check which version it was, so we don’t toggle self.on twice as well: :checkered_flag:

# Only toggles when overloaded callback signature isn't
# ActiveElement::mousePressed():
if args: self.on ^= True
print args, self.on

I believe that’s all for now. As you can see, I’ve fixed the button example, not the slider 1, b/c that’s the 1 I was studying while trying to peruse the Guido source: :upside_down_face:

"""
 Simple Button (Guido)
 ported from Java to Python by fjenett (2014-May-25)
 fix & mod for old Guido by GoToLoop (2019-Mar-30)

 Discourse.Processing.org/t/guido-cannot-work-in-python-mode/9501/10
 GitHub.com/fjenett/Guido/blob/master/examples/mode-python/button/button.pyde
"""

add_library('Guido')

def setup():
    size(400, 400)

    # Workaround for missing overloaded Interactive.make(PApplet, boolean):
    print Interactive.manager
    Interactive.manager = None 
    Interactive.make(this)

    dim = SimpleButton.DIM
    d = (width - dim) / dim
    dd = d << 1

    for y in range(dim, height - d, dd):
        for x in range(dim, width - d, dd):
            SimpleButton(x, y, d, d)


def draw(): clear()


# ActiveElement inheritance replaces Interactive.add(Object):
class SimpleButton(ActiveElement):
    DIM, ON, OFF, OUTLINE = 20, 200, 100, -1

    def __init__(self, x, y, w, h):
        super(SimpleButton, self).__init__(x, y, w, h)
        self.on = False


    # Variant param *args for both sigs ActiveElement::mousePressed() &
    # ActiveElement::mousePressed(float, float):
    def mousePressed(self, *args):
        # Only toggles when overloaded callback signature isn't
        # ActiveElement::mousePressed():
        if args: self.on ^= True
        print args, self.on


    def draw(self):
        stroke(self.OUTLINE) if self.hover else noStroke()
        fill(self.ON if self.on else self.OFF)
        rect(self.x, self.y, self.width, self.height)
2 Likes

Excellent, @GoToLoop! Thanks for the thorough explanation.

I tested this out, and can confirm that fixing the GitHub slider example requires the few adjustments/additions you mentioned – specifically:

class SimpleSlider(ActiveElement):
    ...
    
    #def mouseDragged(self, mx, my, dx, dy ):
    def mouseDragged(self, *args):
        mx = args[0]
        ...

def setup():
    size( 200, 220 )
    Interactive.manager = None
    #Interactive.make(this, True)
    Interactive.make(this)
    ...
2 Likes

@ mouseDragged() I’d add an if len(args) < 4: return check as its 1st statement in order to avoid processing the callback twice needlessly. :nerd_face:

thank everyone,espcially Go ToLoop,for your help,I have resolved the problem.

"""
Slider example
"""

add_library('Guido')

# global slider variable
slider = None

class SimpleSlider(ActiveElement):
    
    def __init__(self, x, y, w, h ):
        super( SimpleSlider, self ).__init__(x,y,w,h)
        self.hover = False
        self.valueX = x
        self.value = 0
    
    def mouseDragged(self,mx,my,*p ):
        self.valueX = mx - self.height/2
        
        if ( self.valueX < self.x ):
            self.valueX = self.x
        
        if ( self.valueX > self.x+self.width-self.height ):
            self.valueX = self.x+self.width-self.height
        
        self.value = map( self.valueX, self.x, self.x+self.width-self.height, 0, 1 )
        
    def draw(self):
        noStroke()
        fill( 210 if self.hover else 150 )
        rect( self.x, self.y, self.width, self.height )
        fill( 235 )
        rect( self.valueX, self.y, self.height, self.height )

def setup():
    size( 200, 220 )
    Interactive.manager = None
    #Interactive.make(this, True)
    Interactive.make(this)
    
    global slider
    slider = SimpleSlider( 10, height-20, width-20, 10 )


def draw():
    background( 255/2 )
    
    fill( 255 - (slider.value * 255) )
    ellipse( width/2, height/2, 150, 150 )
    fill( slider.value * 255 )
    ellipse( width/2, height/2, 70, 70 )
1 Like

Nice variant to def mouseDragged(self, *args):! :+1:
But given the parameter my isn’t used, just mx, just go w/ def mouseDragged(self, mx, *_):. :wink:

Also, no need for self.hover = False inside __init__() though. :nerd_face:
Parent ActiveElement controls that property by itself. :control_knobs: