ofxToggle addListener no matching member

hi,

i am trying to add listeners to ofxToggle using ofxGui. i found this helpful initially (Vector of ofxGui & vector listener callbacks) but i receive "No matching member for call to ‘make_function’ after creating my listener method. i’d like to add the toggle number to a list when it is 1 and erase it from the list if it is 0.

.h

ofxPanel testPanel;
ofxToggle testToggle[5];

vector<int> toggleList;

vector<int>::iterator toggleCntr;

void testPressed(ofxToggle &toggleNumber);

.cpp

void ofApp::setup(){

for(int i = 0; i < 5; i ++){
    testToggle[i].addListener(this, &ofApp::testPressed);
}

testPanel.setup("panel");
for(int i = 0; i < 5; i ++){
    testPanel.add(testToggle[i].setup("testToggle"));
}

}
//--------------------------------------------------------------
void ofApp::testPressed(ofxToggle &toggleNumber){

for(int i = 0; i < 5; i ++) {
    if(toggleNumber == 1) toggleList.push_back(toggleNumber);
    else if(toggleNumber == 0) {
        for(toggleCntr = toggleList.begin(); toggleCntr < toggleList.end(); ++ toggleCntr) {
            if(*toggleCntr == toggleList[i]) toggleList.erase(toggleCntr);
        }
    }
}

}

//--------------------------------------------------------------
void ofApp::draw(){
testPanel.draw();
}

how can i fix the call to the addlistener?

thanks in advance
01

the parameter for the testPressed function is not the toggle itsel but a boolean:

void ofApp::testPressed(bool & pressed){

hi arturo,

i see … but if i want to identify the toggle, don’t i also need to know which one is pressed?

01

yes you can also do:

void ofApp::testPressed(const void * sender, bool & pressed){
    ofxToggle * toggle = (ofxToggle*)sender;
}

i saw that in the other thread, but i don’t understand how to apply it.

the sender is the ofxToggle.

can i do this:

for(int i = 0; i < 5; i ++) {
ofxToggle * toggle[i] = (ofxToggle*)sender;
if(*toggle[i] == 1) toggleList.push_back(toggle[i]);
else if(*toggle[i] == 0) {
for(toggleCntr = toggleList.begin(); toggleCntr < toggleList.end(); ++ toggleCntr) {
if(*toggleCntr == toggleList[i]) toggleList.erase(toggleCntr);
}
}

01

not sure what you mean perhaps it’s easier if you explain what you are trying to do?

when a toggle is pressed (and == 1), i’d like to add it to a sorted list.
when a toggle is pressed (and == 0), i’d like to erase it from the list.

i was trying to do this without listeners and trying to save the state of the toggle when it changes from 0 to 1 and 1 to 0, but since i was doing it in draw(), it was continuously adding the toggle to the list.

01

this compiles, but nothing is printed to the console. i guess it’s because the pressed function is not properly registering toggle presses. when i include indexes (ofxToggle * testToggle[i] = (ofxToggle *)sender), i receive a message about testToggle not being initialized, which it is in .h.

.h

ofxPanel testPanel;
ofxToggle testToggle[5];

vector<int> toggleList;

vector<int>::iterator toggleCntr;

void testPressed(const void * sender, bool &pressed);

.cpp

void ofApp::setup(){

for(int i = 0; i < 5; i ++){
    testToggle[i].addListener(this, &ofApp::testPressed);
}

testPanel.setup("panel");
for(int i = 0; i < 5; i ++){
    testPanel.add(testToggle[i].setup("testToggle"));
}

for(toggleCntr = toggleList.begin(); toggleCntr < toggleList.end(); ++ toggleCntr) {
    cout << *toggleCntr << "\n";
}

for(int i = 0; i < 10; i ++){
    numbers.push_back(i);
}

sort(numbers.begin(), numbers.end(), compareNumbs);
ofSort(numbers, compareNumbs);
}
//--------------------------------------------------------------
void ofApp::testPressed(const void * sender, bool &pressed){

for(int i = 0; i < 5; i ++) {
    
    ofxToggle * testToggle = (ofxToggle*)sender;
    
    if(*testToggle == 1) toggleList.push_back(testToggle[i]);
    else if(*testToggle == 0) {
        for(toggleCntr = toggleList.begin(); toggleCntr < toggleList.end(); ++ toggleCntr) {
            if(*toggleCntr == toggleList[i]) toggleList.erase(toggleCntr);
        }
    }
}
}
//--------------------------------------------------------------
void ofApp::draw(){
    testPanel.draw();
}

01

testToggle[i] will return always 1 or 0 in:

toggleList.push_back(testToggle[i]);

or

*toggleCntr == toggleList[i]

depending if it’s enabled or not not an order number so you can’t use it as an identifier for the toggle you can use instead a pointer to the control

i’ve run into that problem where i can only access of a toggle is enabled or not quite a bit today. if i am receiving the sender as a parameter isn’t this assigning the sender to a toggle (although it won’t let me index it without error):

ofxToggle * testToggle = (ofxToggle*)sender;

even though this doesn’t work, this is what i intended:

for(int i = 0; i < 5; i ++) {
    
    ofxToggle * testToggle[i] = (ofxToggle*)sender;
    
    if(*testToggle[i] == 1) toggleList.push_back(i);
    else if(*testToggle[i] == 0) {
        for(toggleCntr = toggleList.begin(); toggleCntr < toggleList.end(); ++ toggleCntr) {
            if(*toggleCntr == toggleList[i]) toggleList.erase(toggleCntr);
        }
    }
}

01

again, not really sure what you are trying to do with this but if you are just trying to get a list of the toggles that are enabled this should do:

void ofApp::testPressed(bool &pressed){
    toggleList.clear();
    for(int i = 0; i < 5; i ++) {
          if(testToggle[i]){
               toggleList.push_back(i);
          }
    }
}

my aim:
when a toggle is pressed (and == 1), i’d like to add it to a sorted list.
when a toggle is pressed (and == 0), i’d like to erase it from the list.

this compiles as well, but doesn’t print anything to the console, so i am not sure it registering toggle states:

toggleList.clear();
for(int i = 0; i < 5; i ++) {
    if(testToggle[i]){
        toggleList.push_back(i);
        cout << toggleList[i] << ", ";
    }
}

shouldn’t the addlistener for ofxButton and ofxToggle work in the same way? i added some changes to the bell ringing ofxButton example, which doesn’t compile with sending the & pressed parameter and the button doesn’t seem to ever register as rung, although it rings. i am able to print to the console unlike the ofxToggle example discussed, nor does the ofxToggle example compile without sending the & pressed param.

.h

ofParameter<float> radius;
ofParameter<ofColor> color;
ofParameter<ofVec2f> center;
ofParameter<int> circleResolution;
ofParameter<bool> filled;
ofxButton twoCircles;
ofxButton ringButton[5];
ofParameter<string> screenSize;

ofxPanel gui;

vector<int> ringList;

ofSoundPlayer ring[5];

.cpp

//--------------------------------------------------------------
void ofApp::setup(){
ofSetVerticalSync(true);

// we add this listener before setting up so the initial circle resolution is correct
circleResolution.addListener(this, &ofApp::circleResolutionChanged);
for(int i = 0; i < 5; i ++) {
    ringButton[i].addListener(this, &ofApp::ringButtonPressed);
}

gui.setup("panel"); // most of the time you don't need a name but don't forget to call setup
gui.add(filled.set("bFill", true));
gui.add(radius.set( "radius", 140, 10, 300 ));
gui.add(center.set("center",ofVec2f(ofGetWidth()*.5,ofGetHeight()*.5),ofVec2f(0,0),ofVec2f(ofGetWidth(),ofGetHeight())));
gui.add(color.set("color",ofColor(100,100,140),ofColor(0,0),ofColor(255,255)));
gui.add(circleResolution.set("circleRes", 5, 3, 90));
gui.add(twoCircles.setup("twoCircles"));

for(int i = 0; i < 5; i ++) {
    gui.add(ringButton[i].setup("ring"));
}
gui.add(screenSize.set("screenSize", ""));

bHide = false;

for(int i = 0; i < 5; i ++) {
    ring[i].load("ring.wav");
}

}

//--------------------------------------------------------------
void ofApp::exit(){
for(int i = 0; i < 5; i ++) {
ringButton[i].removeListener(this, &ofApp::ringButtonPressed);
}
}

//--------------------------------------------------------------
void ofApp::circleResolutionChanged(int & circleResolution){
ofSetCircleResolution(circleResolution);
}

//--------------------------------------------------------------
void ofApp::ringButtonPressed(){
for(int i = 0; i < 5; i ++) {
ring[i].play();
cout << "button played: " << ringButton[i] << “\n”; //prints to console as “0” even though they ring
if(ringButton[i]) cout << "button played: " << i << “\n”; //does not print to console
if(ringButton[i]){
ringList.push_back(i);
cout << "button: " << ringButton[i] << “\n”; //does not print to console, so ringButton[i] is not enabled even though the bells ring
cout << "rung: " << ringList[i] << “\n”;
}
}
}

//--------------------------------------------------------------
void ofApp::draw(){
ofBackgroundGradient(ofColor::white, ofColor::gray);

if( filled ){
	ofFill();
}else{
	ofNoFill();
}

ofSetColor(color);
if(twoCircles){
	ofDrawCircle(center->x-radius*.5, center->y, radius );
	ofDrawCircle(center->x+radius*.5, center->y, radius );
}else{
	ofDrawCircle((ofVec2f)center, radius );
}

if( !bHide ){
	gui.draw();
}

}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
if( key == ‘h’ ){
bHide = !bHide;
}
if(key == ‘s’) {
gui.saveToFile(“settings.xml”);
}
if(key == ‘l’) {
gui.loadFromFile(“settings.xml”);
}
if(key == ’ '){
color = ofColor(255);
}
}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){
screenSize = ofToString(w) + “x” + ofToString(h);
}

01

i got it to work using ofParameter instead of ofxToggle, with which i was not able to read the state of the toggles.

i still don’t get why the addlistener behaves differently with ofxButton and ofxToggle, but ofParameter seems to work for now.

thanks for your time, arturo!

01