StringDict.get() Problem


#1

Hi All,

Sorry, I’m pretty new to all this. I have a project I’m working on that saves keyboard input to a StringDict with a keyword for each of a number of associated textfield objects.
It seems to be mostly operational, however, when I try to retrieve the associated string so that I can compare it to make things happen–in this case change the colour to green (PASS) or red (FAIL)–it doesn’t seem to work.

I note that I can simply .set() the string that works to the StringDict and it compares just fine, but when I .get() the string from keyboard input, nothing. What am I doing wrong here?

Also maybe there’s a much easier way to do this. Any help and advice would be much appreciated.

Code looks like this:

int border = 10;

//String txt = "";
Textfield[] textfields;
PFont f;
StringDict savedStrings;

color te = color(0); //text color
color ba = color(200); //background color
color bo = color(255); //border color
color se = color(230); //select color
color pf = ba; //pass/fail color

void setup() {
  size(400,200);
  
  String[] keyWords = new String[3];
  keyWords[0] = "Test1";
  keyWords[1] = "Test2";
  keyWords[2] = "Test3";
  
  //Initialise savedStrings with keywords to be associated with text input.
  savedStrings = new StringDict();
  for (int i = 0; i < keyWords.length; i++) {
    savedStrings.set(keyWords[i], "");
  }
  
  //number of textfields
  textfields = new Textfield[keyWords.length];
   
  //Construct textfields 
  for (int i = 0; i < textfields.length; i++) {
    String t = "Click then type PASS or FAIL";
    String k = keyWords[i]; 
    float w = width - border;
    float h = (height / textfields.length) - border;
    float x = width / 2;
    float y = i * (height / textfields.length) + h/2 + border/2;
    int li = 5;
    
    textfields[i] = new Textfield(x,y,w,h,t,k,te,ba,bo,se,li);
  }
}

void draw() {
  for (int i = 0; i < textfields.length; i++) {
    textfields[i].display();
  }
}

void mouseClicked() {
  for (int i = 0; i < textfields.length; i++) {
    if (textfields[i].isFocused) {
      textfields[i].click();     
  } else if (textfields[i].active == true) {
      textfields[i].deactivate();
    }
  }
}

void keyTyped() {
  for (int i = 0; i < textfields.length; i++) {
    if (textfields[i].active == false) {
    //do nothing
  } else if (textfields[i].active == true) {
      textfields[i].tKeyTyped();
        //if (txt == "") {
       // textfields[i].deactivate();
      //}
    }
  }
}
  
//----------------------------------------------  
  
class Textfield {
  final color textC, baseC, bordC, slctC;
  
  String txt = "";
  
  boolean isFocused, active;
  String t, keyWord, state;
  float x, y, w, h;
  int lim;
  
  Textfield(
  float _x, float _y, float _w, float _h, 
  String _t, String _k,
  color te, color ba, color bo, color se,
  int li) {  
    x = _x;
    y = _y;
    w = _w;
    h = _h;  
    t = _t;
    keyWord = _k; 
    textC = te;
    baseC = ba;
    bordC = bo;
    slctC = se;  
    lim = li;
  } 
  
  void display() {
    
    stroke(bordC);
    strokeWeight(border);
    rectMode(CENTER);
    fill(baseC);
    rect(x,y,w,h);
       
    state = savedStrings.get(keyWord);
    
    //Display textfield with mouseover
    if (checkFocus()) {
      fill(slctC);
    } else {
      fill(baseC);
    }
    rect(x,y,w,h);
    
    //Display initial text
    if (state == "") {
    f = createFont("Arial", 15);
    textFont(f);
    textAlign(CENTER, CENTER);
    textSize(15);
    fill(textC);
    text(t, x, y);
    }
    
    //If textfield is clicked, display text being typed. 
    if (this.active == true) {
      fill(slctC);
      rect(x,y,w,h);
      fill(textC);
      text(txt, x, y);
      
    //If textfield deactivated (pressed enter or clicked away) display saved text
    //Color textfield if saved text meets PASS / FAIL criteria.
    } else if (this.active == false && state != "") {
      fill(pf);
      rect(x,y,w,h);
      fill(textC);
      text(state, x, y);
    }
  }

  void deactivate() {
    //txt = "PASS"; //Uncomment to verify PASS / FAIL Operation
  
    savedStrings.set(keyWord,txt);
    println("deactivate_keyWord "+keyWord); println(savedStrings); 
    this.active = false;
    //println(txt);
   
    
    //Check saved text with pass fail criteria, green if PASS, red if FAIL.
    if (savedStrings.get(keyWord) == "PASS") {
      pf = color(0,255,0);
    } else if (savedStrings.get(keyWord) == "FAIL") {
      pf = color(255,0,0);
    }
  }

  void click() {
    this.active = true;
    txt = savedStrings.get(keyWord);
    println("click_keyWord "+keyWord); println("click_txt "+txt); println(savedStrings);
  } 

  void tKeyTyped() {
    char r = key;  
    
    if (r == CODED) return;
    final int len = txt.length();
      
    if (r == BACKSPACE) txt = txt.substring(0, max(0, len-1));
    else if (len >= lim) return;
    else if (r == ENTER || r == RETURN) {
      this.deactivate();
    } else if (r == TAB & len < lim-3)  txt += "    "; 
    else if (r == DELETE)  txt = "";
    else if (r >= ' ')     txt += str(r);
  }
    
  String blinkChar() {
    return (frameCount>>2 & 1) == 0 ? "_" : ""; 
  }
    
  boolean checkFocus() {
    return isFocused = (mouseX > x - width/2 && mouseX < x + width/2 + h && mouseY > y - h/2 && mouseY < y + h/2);
  }
}

#2

pls format your full code, that above is not readable and can not be run.

for my understanding a String dictionary ( you not show the declaration )
https://processing.org/reference/StringDict.html
a ( existing or new ) can be set by

inventory.set(“flour”, “white”);

in that respect i not understand your variable “k”
the String dictionary can not be treated like a array easily
but i did a example for you:

StringDict inventory;
String[] theKeys;
String thevalue = "";

void setup() {
  size(200, 200);
  inventory = new StringDict();
  inventory.set("coffee", "black");
  inventory.set("flour", "white");
  inventory.set("tea", "green");
  println(inventory);
}

void draw() {
  background(200, 200, 0);
  fill(0);
  textAlign(LEFT);
  String[] theKeys = inventory.keyArray();
  for ( int i = 0; i< inventory.size(); i++) {
    thevalue = inventory.get(theKeys[i]);
    text("i: "+i+" key: "+ theKeys[i]+" value: "+thevalue, 20, 20 +i*20);
  }
}

if you use a
https://processing.org/reference/StringList.html
it is different.


#3

Thanks for your feedback kII, like I said I’m new. My full code contains a lot that isn’t relevant to my question so I was hoping that only the relevant section was interpretable.
I’ve whittled it down to an example that can be run.


#4

thank you, good

but you need us to check that now or you understand my example and can work…


#5

Still need help. I think I understand how to use the StringDict for the most part.

If you uncomment line 148 you can see how I want the code to work.
If I just set the txt variable to “PASS”, the following block gets it from the savedStrings StringDict, and the textfield turns green as planned.
If you comment out that line again so that savedStrings is receiving the txt variable from keyboard input, the following block can’t seem to reference it. It prints to the console as “PASS”, but nothing happens.


#6

when i click several times all 3 fields have the same content;
there is a error about using the global “txt” inside the class
it is copying the last typed content arround…

more pls. try to use prints to see what happens inside the dict array
in deactivate()

    savedStrings.set(keyWord,txt);
  if (dprint) { println("deactivate_keyWord "+keyWord); println(savedStrings); }

in click()

    txt = savedStrings.get(keyWord);
  if (dprint) { println("click_keyWord "+keyWord); println("click_txt "+txt); println(savedStrings); }

i would think that the logic is wrong,
because what i expect is that you somewhere do a compare between
if “Test1” equals “typed in txt”
only if that is true you might overwrite it with “PASS” and do the color thing


#7

OK, so I’ve updated the code with “txt” declared within the scope of the class, this seems to stop the crossover problem you noted. Thank you.

The debug prints do help to see what is going on, but it’s still not doing the colour thing even though everything seems correct!
I can’t see any reason why it doesn’t turn green when I type “PASS”. Everything looks exactly as it should in the console.


#8

sorry, that was not clear to me:
you want a action on when the operator type “PASS”
and that you want compare with the string “PASS” if same?
while the keyWord is “Test1”… “Test3” ?
how about “pass” or “PASS” or "PASS "
anyhow a STRING == STRING NOT work!
max like a key == ‘f’ can work. ( possibly you see this in keyboard code )
must use:
https://processing.org/reference/String_equals_.html

hm, but i see some color change here on your old code??


#9

.equals() works!

txt = "PASS"; //Uncomment to verify PASS / FAIL Operation
  
    savedStrings.set(keyWord,txt); 
    this.active = false;
  if (savedStrings.get(keyWord) == "PASS") {
      pf = color(0,255,0);
    } else if (savedStrings.get(keyWord) == "FAIL") {
      pf = color(255,0,0);
    }
  }

Doesn’t explain why that works though…

Anyhow, you’ve got me out hot water for now. Thank you!!!


#10

yes, i did not get into that deeply, but one time i got the impression that
string1 == string2 works for the first character ?? not sure