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. 
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);
}
2 Likes
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!! 
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