Can iterate though all ofxGui elements?

I am adding a bunch for ofParameters to my ofxPanel gui;.

I was hoping to can loop through all those elements and then use myParameter.getName();

I have seen people use listeners to react to changes but I feel that’s not what I need.
I am hoping to find a way to display info text somewhere when my mouse hovers over each gui element.

Thanks for any advice.

Hi there… I don’t use ofxGui much, but from what you’ve written, I assume it’s constructed in a way that all the elements added to the gui panel are NOT stored in one common element vector?

I was hoping I could check if the mouse position is inside the rectangular shape of the gui element. But mouseXY does not get updated as soon as it is over the gui.

    for(auto & cc : gui.getControlNames()){
        ofRectangle temp_rect = gui.getControl(cc)->getShape();
           
        if(temp_rect.inside(mouseX, mouseY)){
            ofLog()<<cc<<guiInfo[cc]<<" mouseInside";
        }
    }

My plan was to use a map and add info to it.

map<string, string> guiInfo;

gui.add(radius.set( "radius", 140, 10, 300 ));
guiInfo["radius"] = "some info about radius";

Then maybe use ofGetMouseX() and ofGetMouseY() instead of mouseX and mouseY…

ofGetMouseX(), ofGetMouseY() are global functions that can be used from anywhere as it is included to the whole ofMain.h header, more explicitly, defined by ofEvents.cpp

2 Likes

thanks so much for the advice.
this works now.

        for(auto & cc : gui_main.getControlNames()){
            ofRectangle temp_rect = gui_main.getControl(cc)->getShape();
            
            if(temp_rect.inside(ofGetMouseX(), ofGetMouseY())){
                ofDrawBitmapString(guiInfo[cc], temp_rect.getRight() + 20, temp_rect.getBottom()-5);
            }
        }
1 Like
1 Like

Hi @stephanschulz
You can do it much simpler without having to call the names, which also should be faster because when you request a control by name it has a for loop that goes through all in order to find the element. Look inside ofxGuiGroup::getControl(const std::string& name){

for(size_t i = 0; i < gui_main.getNumControls (); i++)
{
    ofRectangle temp_rect = gui_main.getControl(i)->getShape();
/// rest of your code.
}
2 Likes

Thanks Roy.
But now I need to change how I add my info to the guiInfo map.

current way:

//map<string, string> guiInfo;
gui_main.add(saveX.set("saveX",0,-3000,3000));
guiInfo["saveX"] = "output .svg needs to get position adjusted";

possible new way:

//map<ofxBaseGui *, string> guiInfo;
gui_main.add(saveScaleY.set("saveScaleY",-1,-1,1));
guiInfo[gui_main.getControl(gCnt)] = "output .svg scale needs to be adjusted to fit the file dimensions.";
gCnt++

Ah I see.
although you could do the following without having to change the guiInfo map.

for(size_t i = 0; i < gui_main.getNumControls (); i++)
{
    auto control = gui_main.getControl(i);
    ofRectangle temp_rect = control->getShape();
    
    if(temp_rect.inside(ofGetMouseX(), ofGetMouseY())){
                ofDrawBitmapString(guiInfo[control->getName()], temp_rect.getRight() + 20, temp_rect.getBottom()-5);
            }

}

Thank you all very much for your advice.

This method has worked well for me.
But I am now noticing that when adding a ofParameterGroup to a ofxPanel gui like so gui_main.add(parameters_dmx); that .getNumControls() does not list the group elements, but only the group header.
I will look around and see if I can find a solution for this.

The ofParameterGroupTooltip is nice but I guess I want to see if there is a way to use my on recipe.

I found a workaround by casting the gui element in to a string and checking it for :

void ofApp::drawGuiInfo(ofxPanel & _gui, ofTrueTypeFont & _font){

    //iterate through all elements of this gui
    for(int i = 0; i < _gui.getNumControls (); i++){
        auto control = _gui.getControl(i);

        //check if one of the elements might be a parameterGroup; i.e. parameter contains multiple items
        string paramString = ofToString(control->getParameter());
        
        if( ofIsStringInString(paramString, ":") ){
            //it's a group, so iterate through each group element
            ofxGuiGroup aGroup = _gui.getGroup(control->getName());
            
            for(int n = 0; n < aGroup.getNumControls(); n++){
                 auto g_control = aGroup.getControl(n);
                 drawGuiInfo_element(g_control->getName(),g_control->getShape(), _font);
            }
            
        } else{
            //it's a parameter
            drawGuiInfo_element(control->getName(),control->getShape(), _font);
        }
    }

}

void ofApp::drawGuiInfo_element(string _name, ofRectangle _rect, ofTrueTypeFont & _font ){

    if(_rect.inside(ofGetMouseX(), ofGetMouseY())){
        
        if(guiInfo[_name] != ""){
            
            string str = guiInfo[_name];
            
            float temp_w = _font.stringWidth(str)* 1.1;
            ofSetColor(255,255);
            ofFill();
            ofDrawRectangle(_rect.getRight() + 19, _rect.getBottom()-20, temp_w, 20);
            
            ofSetColor(0,255);
            _font.drawString(str, _rect.getRight() + 22, _rect.getBottom()-5);
        }
    }
    
}
1 Like