G4P GTextField not gaining full focus with multiple text fields

edited August 4 in Library Questions

[edit] the problem, in a nutshell, is summarised in the solution at the end of this post.

Hi, I have a sketch that periodically asks the user for some simple text input via a GTextField (actually multiple fields and GTabManager). There is no mouse used in the application so I am relying on the setVisible and setFocus methods to render the text field when it is needed.

The problem is that if the field starts out invisible and then is made visible it does not have focus, ie the caret is not visible or blinking. I have confirmed that the "GETS_FOCUS" event is fired when setFocus is set to true. The only way to 'activate' the field is to click with the mouse (unwanted). When the field is not in use I have setVisible, setEnabled and setFocus all false, and set them true when user input is required.

Am I using the right approach or is this a bug?

Thanks!

Processing 3.3.5, default renderer.

Answers

  • I can imagine a situation where a number of textfields are made visible at the same time but then they can't all receive focus, and there is no reason that a particular textfield should receive focus.

    When the textfield becomes visible then set its focus to true.

    textfield.setVisible(true);
    textfield.setFocus(true);
    

    You say you don't use the mouse so what event determines when the textfield becomes visible?

  • edited July 31

    I use four text fields that I initialise with new GtextField and the following when the program starts:

    txf2.setFocus(false);
    txf2.setVisible(false);
    txf2.setEnabled(true);
    

    (4 times)

    At the point in the program where I require user input I 'activate' the fields with:

      txf2.setVisible(true);
      txf2.setFocus(false);
    

    for each of the fields but txf1.setFocus(true) for the first of the fields - this does trigger a GETS_FOCUS event and puts a narrow yellow box in the first field, but no caret. GTabManager is used to navigate between fields with the tab key. keyReleased() events are used to detect various non-printing character key presses, for example, "Enter" in any of the text fields completes the user text entry mode.

  • Create a very small sketch (that I can run) to demonstrate what you mean.

  • edited August 1

    Thanks for your help Quark!

    This seems to show the problem (no blinking caret when 'm' is pressed to activate the text fields):

        import g4p_controls.*;
        import java.awt.Font;
    
        GTextField txf1, txf2, txf3, txf4;
        GTabManager tt;
    
        boolean menuDataEntryActive = false; 
        boolean startAddr = false;
    
        int sw, sh;
        String userAddr = "nothing yet";
    
        void setup()
        {
          size(1280, 720);
          sw = width;
          sh = height;
          setupTextEntry();
        }
    
        void draw()
        {
          background(0);
          textSize(30);
          text("Text entered :"+userAddr, 10, 100);
        }
    
        void keyPressed() {
          if (menuDataEntryActive) {
            if (keyCode == 10) {     // enter key
              userAddr = txf1.getText(); 
              hideTextFields();
              menuDataEntryActive = false;
              return;
            }
          } else 
          {
            if (key == 'm') {          // show menu key
              showTextFields();
              menuDataEntryActive = true;
            }
          }
        }
    
        void setupTextEntry() {
          Font font = new Font("Arial", Font.PLAIN, 14);
          G4P.setGlobalColorScheme(GCScheme.PURPLE_SCHEME);
          txf1 = new GTextField(this, sw/2-515, sh/2-130, 300, 20);
          txf1.tag = "txf1";
          txf1.setFont(font);
          txf1.setFocus(false);
          txf1.setVisible(false);
          txf1.setEnabled(true);
    
          txf2 = new GTextField(this, sw/2-370, sh/2-2, 150, 20);
          txf2.tag = "txf2";
          txf2.setFont(font);
          txf2.setFocus(false);
          txf2.setVisible(false);
          txf2.setEnabled(true);
    
          txf3 = new GTextField(this, sw/2-370, sh/2+29, 150, 20);
          txf3.tag = "txf3";
          txf3.setFont(font);
          txf3.setFocus(false);
          txf3.setVisible(false);
          txf3.setEnabled(true);
    
          txf4 = new GTextField(this, sw/2-370, sh/2+60, 150, 20);
          txf4.tag = "txf4";
          txf4.setFont(font);
          txf4.setFocus(false);
          txf4.setVisible(false);
          txf4.setEnabled(true);
    
          // Create the tab manager and add these controls to it
          tt = new GTabManager();
          tt.addControls(txf1, txf2, txf3, txf4);
        }
    
        void showTextFields() {
          txf1.setVisible(true);
          txf1.setFocus(true);
          txf2.setVisible(true);
          txf2.setFocus(false);
          txf3.setVisible(true);
          txf3.setFocus(false);
          txf4.setVisible(true);
          txf4.setFocus(false);
        }
    
        void hideTextFields() {
          txf1.setFocus(false);
          txf1.setVisible(false);
          txf2.setFocus(false);
          txf2.setVisible(false);
          txf3.setFocus(false);
          txf3.setVisible(false);
          txf4.setFocus(false);
          txf4.setVisible(false);
        }
    
        public void displayEvent(String name, GEvent event) {
          String extra = " event fired at " + millis() / 1000.0 + "s";
          print(name + "   ");
          switch(event) {
          case CHANGED:
            println("CHANGED " + extra);
            break;
          case SELECTION_CHANGED:
            println("SELECTION_CHANGED " + extra);
            break;
          case LOST_FOCUS:
            println("LOST_FOCUS " + extra);
            break;
          case GETS_FOCUS:
            println("GETS_FOCUS " + extra);
            break;
          case ENTERED:
            println("ENTERED " + extra);  
            break;
          default:
            println("UNKNOWN " + extra);
          }
        }
    
        public void handleTextEvents(GEditableTextControl textControl, GEvent event) { 
          displayEvent(textControl.tag, event);
        }
    
  • edited August 4 Answer ✓

    Solved it. In a multi text field layout, the field that needs to have focus, and be ready for text entry, should be the LAST field that setFocus(true) is applied to.

    The following code is the bare minimum to show the issue. Neither field is in focus and ready to type text, it has to be selected with a mouse click. The txf2.setFocus(false) seems to override the first txf1.setFocus(true) instruction.

    If the first txf1.setFocus(true) is commented out and the second txf1.setFocus(true) is uncommented then it will work - the first text field will be in focus and ready to enter text (a blinking cursor).

    GTextField txf1, txf2;
    
    void setup()
    {
      size(600, 500);
      txf1 = new GTextField(this, 100, 100, 300, 20);
      txf1.tag = "txf1";
      txf1.setFocus(true);
      txf1.setVisible(true);
      txf1.setEnabled(true);
    
      txf2 = new GTextField(this, 100, 140, 150, 20);
      txf2.tag = "txf2";
      txf2.setFocus(false);
      txf2.setVisible(true);
      txf2.setEnabled(true);
    
      // txf1.setFocus(true);
    }
    
    void draw()
    {
      background(0);
      textSize(30);
      text("Text entered :"+txf1.getText(), 10, 300);
    }
    
  • Answer ✓

    I should point out that only one control at a time can have focus. This is not unique to G4P it is the standard behaviour of all GUIs, the focus determines which control receives user input. When you log on to this forum the user name and password fields can't both have focus at the same time.

    In G4P when you use setFocus the focus is removed from the previous focused control, same as any other GUI

    Glad you like G4P :)

  • edited August 5

    The txf2.setFocus(false) seems to override the first txf1.setFocus(true) instruction.

    Maybe I'm not understanding what it does, but why would calling setFocus(false) clear the previous focus, when false means that no new GUI element has focus? We aren't going from 1 focused element to 2 -- we expect to go from 1 to the-same-1, but instead go from 1 to 0 elements with focus. That behavior doesn't seem related to the not-more-than-one-at-a-time rule.

  • If I understand you correctly then I agree @Jeremydouglass, the behaviour is not self-evident. I understood that only one field can have focus and assumed I would have to manage that programmatically using setFocus(false). But there must be an overseeing GUI manager which does it and setFocus(false) is redundant unless you want NO field to have focus. The more you know, the more you realise how much you don't know.

Sign In or Register to comment.