ofParameter add listener not working

Hi I tried to add a listener to an ofParameter, however I get build errors on xcode. Wich is wreird as a parameter should be able to have a listener.

Screenshot 2023-04-14 at 13.00.43

Screenshot 2023-04-14 at 13.10.38

Class ServerConfig

    public:
       ofParameter<string> url;
       ofParameter<int> ntpPort;

Class ServerConfigPanel

/*
     *  add listener
     */
    template <class ListenerClass, typename ListenerMethod>
    void addListenerServerValues(ListenerClass *listener, ListenerMethod method)
    {
        ntpField.addListener(listener, method); // this one will forward the listener to the appropiate parameter (stored in config->server->ntpPort)
        config->server->ntpPort.addListener(listener, method); // this is a direct call to the parameter
// both calls individually will give the compile error shown in the image
    }

ServerConfigController constructor

        views->serverConfigPanel->addListenerServerValues(this, &ServerConfigController::fieldchangeServerDestination);

openframeworks V0.11.2 (main release)
addons

  • csv
  • gui
  • network
  • xmlSettings

Adding a listener to a ofxButton in the same fashion works like a charm, so to my surprise this did not work. Am i doing it wrong because we are using an ofParameter, am I missing something? or is something wrong in ofParameter?

Ultimate goal.
When something in the server configuration changes i need to call our ntp syncing function to update our ntp timestamp and reset the internal openframeworks clock

After 15 minutes: I created a workaround to add an extra button to trigger the sync after you changes the values, but still I do not understand why the listener on the parameter is not working.

Hey @adminfriso , I’m not super great with listeners but I’ll try and be helpful.

You might find this forum thread of interest: ofParameter addListener doesn't match overloads

I tried a simple, non-templated example and got the same error until I added an argument of the correct type to the function called by the listener (in psudeo-code):

// in ofApp.h
    void printValue(int& value);
    void printParam();
    ofParameter<int> param;

// in ofApp::setup()
    param.set(0);
    // this works; printValue() takes an int& arg:
    param.addListener(this, &ofApp::printValue);
    // this doesn't work; printParam() has incorrect arg type:
//    param.addListener(this, &ofApp::printParam); 

// in ofApp.cpp
void ofApp::printValue(int& value){
    std::cout << "printValue(): " << value << std::endl;
}
void ofApp::printParam(){
    std::cout << "printParam(): " << param.get() << std::endl;
}

So perhaps ServerConfigController::fieldchangeServerDestination() has missing or incompatible argument types (either explicitly or from the templates).

Also I LOVE using ofEventListener with an ofParameter. It’s an object so it gets destroyed when it goes out of scope. I’ve never templated it though, so you’d have to try it and see if it works. I use it with a lambda like this:

// in ofApp.h
void printValue(const ofParameter<int>& p);
void printParam();
ofParameter<int> param;
ofEventListener paramListener;

// in ofApp::setup()
paramListener = param.newListener([this](const ofParameter<int>& p) {
    // p captures the parameter by reference;
    // run a local function here, and/or
    // call functions in ofApp,:
    printValue();
    // and/oror pass p to a function in ofApp:
    printValue(p);
});

// in ofApp.cpp
void ofApp::printValue(const ofParamter<int>& p){
    std::cout << "printValue(): " << p.get() << std::endl;
}
void ofApp::printParam(){
    std::cout << "printParam(): " << param.get() << std::endl;
}
1 Like

Hi @adminfriso
I think that the problem has to do with the ofParameter template type and the arguments of the passed function.
the rule is simple, the passed function must have an argument that is a reference of the same type of the ofParameter template type.
Example:

class DummyClass{
public:
ofParameter<int> intParam;

void intParamCallback(int & i){ // notice that the argument is an int reference
// do something.
}

intParam.addListener(this, &DummyClass::intParamCallback); // notice the & before passing the callback.


};

Thus, it is really important what you are passing to your addListenerServerValues function.
let me know if this is helpful.

1 Like

thanks for your help, indeed I did not know i had to add a reference to the parameter type, and the xcode logging was unclear about this. works like a charm now.

Next time I will need to use a listener I will test the EventListener to see if I am also going to love it!

thanks for your help, indeed I did not know i had to add a reference to the parameter type, and the xcode logging was unclear about this. works like a charm now.

1 Like