Need help with ofParameter and Listeners!

Good morning,

I hope you’re all doing well.

I’m using an ofParameter<std::string> text_input; with an ofxPanel gui; form ofxGui.h, to generate a single text input box, where the user can input a text string.

Now, I want to verify in ofApp::update();, whether the text input has changed or not, compared to the previous state.
I’m currently comparing the previous to the current string, but I recon that’s what listeners are for?

I’ve looked at the documentation but the information is quite sparse. :wink:
Can somebody please explain how listeners work and how I can add one to my text field, and use it to see if the user input has changed.

Thank you.

hey @diff-arch,

here you have a simple example.

I added a boolean to clear the string. To make a button you can use a void parameter too instead of the bool.
Usually, you can group many parameters into an ofParameterGroup, and to check which parameter changed on the callback.
You can check around /openFrameworks/examples/gui/parameterGroupExample to other examples.

ofApp.h

#pragma once

#include "ofMain.h"

#include "ofxGui.h"

class ofApp : public ofBaseApp{

	public:

    void setup();
    void draw();
    void exit();

    ofxPanel gui;

    ofParameter<std::string> text_input;
    ofParameter<bool> bClear;

    void Changed_string(string & s);
    void Changed_Clear(bool & b);
};

ofApp.cpp

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
    ofSetFrameRate(25);

    text_input.set("input your text", "");
    text_input.addListener(this, &ofApp::Changed_string);

    bClear.set("Clear", false);
    bClear.addListener(this, &ofApp::Changed_Clear);

    gui.setup();
    gui.add(text_input);
    gui.add(bClear);
}

//--------------------------------------------------------------
void ofApp::draw(){
    gui.draw();

    ofDrawBitmapStringHighlight(text_input.get(), 300, 50);
}

//--------------------------------------------------------------
void ofApp::Changed_string(string &s){
    cout << "input text: " << s << endl;
}

//--------------------------------------------------------------
void ofApp::Changed_Clear(bool & b){
    if (b) b = false;
    cout << "clear" << endl;
    text_input = "";
}

//--------------------------------------------------------------
void ofApp::exit(){
    text_input.removeListener(this, &ofApp::Changed_string);
    bClear.removeListener(this, &ofApp::Changed_Clear);
}
1 Like

Hello @moebiussurfing,

Thank you for your reply! This doesn’t seem to work for me though. I get a semantic issue:

No matching member function for call to make_function (ofEvent.h, line 553)

Could you please take a look at my code?
Here are the relevant parts:

ofApp.h

#pragma once

#include <string>
#include "ofMain.h"
#include "ofxGui.h"

class ofApp : public ofBaseApp{

	public:
		void setup();
		void update();
		void draw();
        void exit();
        
    void textChanged(bool& text_changed);
    
    ofxPanel gui;
    ofParameterGroup parameters;
    ofParameter<std::string> text_input;
    bool text_changed = false; // <- value to be changed

};

ofApp.cpp

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
    parameters.setName("Controls");
    parameters.add(text_input.set("Input text here"));
    text_input.addListener(this, &ofApp::textChanged);
    
    gui.setup(parameters);    
}

//--------------------------------------------------------------
void ofApp::update(){
    if (text_changed) {
        
		// Updating some stuff if text input changed
		
    }
}

//--------------------------------------------------------------
void ofApp::draw(){
	// Drawing some of the updated stuff
    
    gui.draw();
}


//--------------------------------------------------------------
void ofApp::textChanged(bool& text_changed) {
    // Should chnage text_changed to true
    if (!text_changed)
        text_changed = true;
}

//--------------------------------------------------------------
void ofApp::exit() {
    text_input.removeListener(this, &ofApp::textChanged);
    
}

Any ideas?

Thanks again.

your callback handles a bool, but must be a string type.
the variable name could be different bc it’s a reference to the original variable.

#pragma once

//#include <string>
#include "ofMain.h"
#include "ofxGui.h"

class ofApp : public ofBaseApp{

public:
    void setup();
    void update();
    void draw();
    void exit();

    void textChanged(string& s);

    ofxPanel gui;
    ofParameterGroup parameters;
    ofParameter<std::string> text_input;
    bool text_changed = false; // <- value to be changed

};
#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
    parameters.setName("Controls");
    parameters.add(text_input.set("Input text here"));
    text_input.addListener(this, &ofApp::textChanged);

    gui.setup(parameters);
}

//--------------------------------------------------------------
void ofApp::update(){
    if (text_changed) {

        // Updating some stuff if text input changed
        text_changed = false;//already checked
    }
}

//--------------------------------------------------------------
void ofApp::draw(){
    // Drawing some of the updated stuff

    gui.draw();
}

//--------------------------------------------------------------
void ofApp::textChanged(string& s) {
    // Should chnage text_changed to true
    if (!text_changed)
        text_changed = true;

   //doRefreshFunction(). above bool not required for this
}

//--------------------------------------------------------------
void ofApp::exit() {
    text_input.removeListener(this, &ofApp::textChanged);
}
1 Like

Ha, now it works! Thank you very much, @moebiussurfing!! :slight_smile:

So the argument std::string s refers to ofParameter<std::string> text_changed, and the method name ofApp::textChanged(..) can be different because it’s already linked as listener to the ofParameter in ofApp::setup()?

Thanks again.

you’re welcome. yes, you get the same result if you do:

void ofApp::textChanged(string& s) {
    cout << s << endl;
    cout << text_input.get() << endl;
}
1 Like