G4P textArea Questions (delete text in textArea, textArea text jittering)

Hi There,
first of all: the G4P GUI builder is awesome, thanks for such a great tool.
I am using the tool together with the grafica library to make a graphic plotter applet with multiple windows (main, settings, help…). I’ve come a long way and managed to get almost anything to work, googling questions i had along the way. But now i have to ask some questions:

  1. textArea: delete the Text. I found this similar topic https://forum.processing.org/one/topic/g4p-how-to-clear-delete-text-from-a-gtextfield.html but since it is about the textField, not textArea, the solution didnt work. Since you can only send strings the same size as the existing one, and replacing the text with an empty string[] also doesn’t work, i’m asking for your help. The closest i came to a solution was to replace everything with " " (spaces), but that’s not what i wanted. In the end i just want to save the entered text to a string and afterwards delete the text I entered in the textArea. In my despair I even tried to simulate a DELETE/BACKSPACE-key action targeted at the textArea (and failed).

  2. The text shown in small textAreas jitters like crazy when the program is running. If i make the areas large enough, it stops, but the “small” areas are still large enough to fit text in it (so it looks at least). Is there a lower limit on how small a textarea is allowed to be? Or known issues when it gets too small?
    EDIT: I found the lower limit to be height=60 when the font is Arial, plane, size 20, the width seems not to be critical (worked at 30). Lower than height 60 and it jitters. Guess i’ll just adjust my window to that limits.

Since it is plenty of (mostly unrelated) code in two tabs, I don’t know what specific code to post? The gui handlers are mostly filled with one-liners, otherwise untouched. I guess these are more of base-knowledge questions?

Thanks for any helpful answers.

Glad you find GUI Builder and G4P awesome, always nice to get positive feedback :grin:

So taking each point in turn lets assume we have a GTextArea called txa

textArea: delete the Text
I assume by this you want to delete all the text in the textarea in which case you can use
txa.setText("");

You can even use an array of empty strings like this
txa.setText(new String[] { "", "" });

but you cannot use an empty array (i.e. a zero length array), this doesn’t work which makes sense to me since you are not providing any Strings to work with.
txa.setText(new String[0]);

The text shown in small textAreas jitters
This is a new one on me and you are the first person to have reported it.

I must ask the question “Why are you using such a small textarea?” since without scrollbars most of the text will be un-viewable anyway, why not use a textfield instead?

Having said that I will investigate the jittering problem further.

Just in case you have further questions I have included here a small test sketch I created to try out some of your issues. You can always modify the main code to demonstrate any issues I have missed.

import g4p_controls.*;

GTextField txf;
GTextArea txa;
GLabel lbl;
GButton btn0;

void setup() {
  size(400, 500);
  txf = new GTextField(this, 10, 10, 100, 20);
  txa = new GTextArea(this, 10, 60, 100, 30);
  lbl = new GLabel(this, 10, 120, width - 20, height - 130);
  lbl.setOpaque(true);
  txf.setText(text2);
  txa.setText(text2);
  btn0 = new GButton(this, width - 120, 20, 55, 40, "Clear Text");
  btn0.addEventHandler(this, "clearText");
  btn0 = new GButton(this, width - 60, 20, 55, 40, "Copy Text");
  btn0.addEventHandler(this, "copyText");
}

void draw() {
  background(200, 200, 255);
}

public void clearText(GButton button, GEvent event) { 
  txa.setText("");
  //txa.setText(new String[0]);  // Zero element array doesn't work
  //txa.setText(new String[] { "", "" });  // Array with empty strings as elements work
}

public void copyText(GButton button, GEvent event) { 
  String s = txa.getText();
  txa.setText("");
  lbl.setText(s);
}

String text0 = "Quark exists";
String text1 = "The rain in Spain falls mainly in the plane";
String text2 = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. " 
  + "Lorem Ipsum has been the industry's standard dummy text ever since the " 
  + "1500s, when an unknown printer took a galley of type and scrambled it to" 
  + " make a type specimen book. It has survived not only five centuries, but " 
  + "also the leap into electronic typesetting, remaining essentially unchanged. " 
  + "It was popularised in the 1960s with the release of Letraset sheets " 
  + "containing Lorem Ipsum passages, and more recently with desktop publishing " 
  + "software like Aldus PageMaker including versions of Lorem Ipsum." 
  + "Contrary to popular belief, Lorem Ipsum is not simply random text. It has " 
  + "roots in a piece of classical Latin literature from 45 BC, making it over " 
  + "2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney " 
  + "College in Virginia, looked up one of the more obscure Latin words, consectetur, " 
  + "from a Lorem Ipsum passage, and going through the cites of the word in classical " 
  + "literature, discovered the undoubtable source. Lorem Ipsum comes from sections " 
  + "1.10.32 and 1.10.33 of 'de Finibus Bonorum et Malorum' (The Extremes of Good " 
  + "and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory " 
  + "of ethics, very popular during the Renaissance." 
  + "It is a long established fact that a reader will be distracted by the readable " 
  + "content of a page when looking at its layout. The point of using Lorem Ipsum " 
  + "is that it has a more-or-less normal distribution of letters, as opposed to " 
  + "using 'Content here, content here', making it look like readable English. Many " 
  + "desktop publishing packages and web page editors now use Lorem Ipsum as their " 
  + "default model text, and a search for 'lorem ipsum' will uncover many web sites " 
  + "still in their infancy. Various versions have evolved over the years, sometimes " 
  + "by accident, sometimes on purpose (injected humour and the like)";
2 Likes

Thank you for the quick response!

  1. While investigating the error recreation code of yours (thanks for the expense) I think i found my error and realized i just should have posted my code from the beginning, sorry.
public void textarea3_change1(GTextArea source, GEvent event) { //_CODE_:textarea3_Eingabe:602026:
  if (event==GEvent.ENTERED){
    doEingabe(textarea3_Eingabe.getText(0)); //my function in the main tab
    textarea3_Eingabe.setText("");
    }

It has to do with the handler reacting on ENTERED. Because if i change it to something else, the code works. With “entered” i get this error instead: java.lang.StringIndexOutOfBoundsException: String index out of range: 3, where 3 is my real entered text length-1. When i change the event to LOST_FOCUS, it pretty much does what i wanted from the beginng. But whats the deal with ENTERED then?

  1. Haha, I expected you to ask me why i use such small textAreas. With your provided sample code i figured out i did not read the built in G4P reference well enough. With textArea, getText() is directly in “Public Member Functions”, with TextField it is under " Methods inherited from class g4p_controls.GEditableTextControl" an i simply overlooked this and thought from that moment on i had to use textArea if I want to get more than just a number value out of it.

So you pretty much solved all my issues in one go, big thanks for that. If you just could tell me why the ENTERED event throws an error, that would be great.

OK I have checked the source code and there is no bug. The jittering is caused by the code scrolling the text inside the textarea to keep the text insertion point in the visible area. If the GTextArea is too short then it wants to both scroll up and scroll down and flips between the two causing the jitter.

I worked on the assumption that anyone using a GTextArea will want to see at least 2 lines of text otherwise they would have used a GTextField. This seems a reasonable assumption.

So the minimum height of a GTextArea is
= 2 * line height + 12 pixels
now the line height includes the spacing between lines so is ~1.5 * font height so that becomes
~ 3 * font height + 12 pixels

1 Like

Yes i guess this is absolutely fine, but you know the end user (me) is always stupid enough to do unreasonable things and use things the way they were not designed for. Since I now know all the answers, i’m going to use the controls as intended :grin:

I have no idea since I couldn’t duplicate the problem but if you have a string on length 3 then the indices go between 0-2 so using an index value of 3 would be out of range.

It is always best to check the type of event GTextField and GTextArea controls can fire
ENTERED
CHANGED
SELECTION_CHANGED
GETS_FOCUS
LOST_FOCUS
so pick the one that does what you want.

1 Like

I recreated it with your sample sketch, so you can see what happens if you want.
If you type a text in the textArea and hit enter, the error occurs.

import g4p_controls.*;

GTextField txf;
GTextArea txa;
GLabel lbl;
GButton btn0;

void setup() {
  size(400, 500);
  txf = new GTextField(this, 10, 10, 100, 20);
  txa = new GTextArea(this, 10, 60, 100, 30);
  lbl = new GLabel(this, 10, 120, width - 20, height - 130);
  lbl.setOpaque(true);
  txf.setText(text2);
  txa.setText(text2);
  txa.addEventHandler(this, "enterText");
  btn0 = new GButton(this, width - 120, 20, 55, 40, "Clear Text");
  btn0.addEventHandler(this, "clearText");
  btn0 = new GButton(this, width - 60, 20, 55, 40, "Copy Text");
  btn0.addEventHandler(this, "copyText");
}

void draw() {
  background(200, 200, 255);
}

public void clearText(GButton button, GEvent event) { 
  txa.setText("");
  //txa.setText(new String[0]);  // Zero element array doesn't work
  //txa.setText(new String[] { "", "" });  // Array with empty strings as elements work
}

public void copyText(GButton button, GEvent event) { 
  String s = txa.getText();
  txa.setText("");
  lbl.setText(s);
}

public void enterText(GTextArea txa, GEvent event) { 
  if (event==GEvent.ENTERED){
      String s = txa.getText();
      txa.setText("");
      lbl.setText(s);
  }
}
String text0 = "Quark exists";
String text1 = "The rain in Spain falls mainly in the plane";
String text2 = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. " 
  + "Lorem Ipsum has been the industry's standard dummy text ever since the " 
  + "1500s, when an unknown printer took a galley of type and scrambled it to" 
  + " make a type specimen book. It has survived not only five centuries, but " 
  + "also the leap into electronic typesetting, remaining essentially unchanged. " 
  + "It was popularised in the 1960s with the release of Letraset sheets " 
  + "containing Lorem Ipsum passages, and more recently with desktop publishing " 
  + "software like Aldus PageMaker including versions of Lorem Ipsum." 
  + "Contrary to popular belief, Lorem Ipsum is not simply random text. It has " 
  + "roots in a piece of classical Latin literature from 45 BC, making it over " 
  + "2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney " 
  + "College in Virginia, looked up one of the more obscure Latin words, consectetur, " 
  + "from a Lorem Ipsum passage, and going through the cites of the word in classical " 
  + "literature, discovered the undoubtable source. Lorem Ipsum comes from sections " 
  + "1.10.32 and 1.10.33 of 'de Finibus Bonorum et Malorum' (The Extremes of Good " 
  + "and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory " 
  + "of ethics, very popular during the Renaissance." 
  + "It is a long established fact that a reader will be distracted by the readable " 
  + "content of a page when looking at its layout. The point of using Lorem Ipsum " 
  + "is that it has a more-or-less normal distribution of letters, as opposed to " 
  + "using 'Content here, content here', making it look like readable English. Many " 
  + "desktop publishing packages and web page editors now use Lorem Ipsum as their " 
  + "default model text, and a search for 'lorem ipsum' will uncover many web sites " 
  + "still in their infancy. Various versions have evolved over the years, sometimes " 
  + "by accident, sometimes on purpose (injected humour and the like)";

Anyways, thanks for your help!

This is the event handler for the textarea control txa you are not allowed to modify the text of a control in its own event handler so the statement
txa.setText("");
is not permitted inside the event handler or in any method called by the event handler.

2 Likes

Thanks for the clarification. I thought something like that, changing a text in a handler that reacts to changing text didnt sound quite right.

Hi Peter,

I’ve run into the jitter too, when I want a large font displayed but I don’t want a tall window with the textarea control.

I understand your reasoning regarding the scrollbars, which therefore leaves jitter if the window height is too small, but you have some nice features in the textarea that you don’t have in the textfield, such as the ability to insert text into any location in the textarea. With textfield, you can only append.

Also, it’s such a terrific library, and having a jittery box just doesn’t stand up to the standards you’ve set (on this entirely FREE RESOURCE you have provided…for FREE!)

Any chance to have an option to disable the scroll behavior to allow for a one-line version of the text area? Or somehow get rid of the jitter, maybe with a behind the scenes option to disable scroll bar behavior?

Sorry for asking so much. Such a great library!

If not, I can get by with the textfield, but the textarea suits much better what I’m doing. And the jitter kills it.

Thanks Peter; great work as usual.

Mike

That is incorrect. GTextField supports copy and paste anywhere along the length of the displayed text. The only real differences between these controls are

  • the text field only supports a single line of text (does not support end-of-line characters)
  • the text field only supports a horizontal scroll bar (vertical scrollbar is redundant)

You might try out the G4P_EditTextControls example that comes with the library to check this for yourself.

The jittery text has nothing to do with scrollbar behaviour

simply increase the height of the text area as suggested above.

What are you trying to do?

1 Like

Thank you Peter for your time and explanations. I really appreciate it.

The ta control has the ability to insertText at any point, whereas the tf control does not - tf has appendText at the end.

I’m building an app and I’d like to be able to insert special characters into the tf control at the insertion point/caret. While I can get by without being able to insert at the caret, it’s not ideal, and I’ve no idea how to get it to work otherwise.

Forgive me if I’m wrong, but I cannot copy/paste into a tf control at all; nothing happens.

Is there an issue with allowing the ta control to be just one line?

Also, having the ability to filter input for both controls would be amazing - say, only allow text, or only allow integers, and limit the number of characters I can input. I’ve gotten so far in building my app, but I’m afraid not being able to filter data input is the deal breaker at the moment. I can’t afford to have text in a number field.

And if you are not able/willing to add these to the library, is there some kind of workaround to implement filtering input?

All my best, and thank you again so much for your amazing library, given so freely and generously.

Sorry I was selecting and copying paste with the keyboard, I missed that the textfield has no insertText method. I will add these to the next release of G4P

This works for me

  1. Use the mouse to select some text in a textfield or textarea
  2. Hit Ctrl+C to copy selected text
  3. Click on the textfield where you want to paste text
  4. Click or use arrow keys to move caret
  5. Hit Ctrl+V to paste

No you just have to be careful that text does not wrap to a second line. The trick here is to set the text wrap width(in pixels) after the textarea control has been created e.g.

// txa1 = GtextArea control
// Set the wrap length to 1000 pixels before text is wrapped onto a second line
txa1.getStyledText().setWrapWidth(1000);

I have looked at doing this before but it was impracticable to modify G4P to do this without major changes to the source code.

One possible alternative is to validate the input and change the colour scheme for the textfield if the text is invalid. Try this sketch to see what I mean.

import g4p_controls.*;

GTextField txf1, txf2, txf3, txf4;

public void setup() {
  size(400, 200, JAVA2D);
  createGUI();
}

public void draw() {
  background(230, 230, 255);
}

public void txf1Change(GTextField source, GEvent event) {
  Validate.Integer(source);
}

public void txf2Change(GTextField source, GEvent event) {
  Validate.Integer(source, -50, 100);
}

public void txf3Change(GTextField source, GEvent event) {
  Validate.Float(source);
}

public void txf4Change(GTextField source, GEvent event) {
  Validate.Float(source, - Float.MAX_VALUE, -Float.MIN_VALUE);
}

static class Validate {
  // Additional validation methods can be added to suit your needs 
  public static Integer Integer(GTextField tf) {
    tf.setLocalColorScheme(GCScheme.BLUE_SCHEME);
    Integer n = null;
    try {
      n = Integer.parseInt(tf.getText());
    }
    catch(NumberFormatException nfe) {
      tf.setLocalColorScheme(GCScheme.RED_SCHEME);
    }
    return n;
  }

  public static Integer Integer(GTextField tf, int low, int high) {
    Integer n = Validate.Integer(tf);
    if (n != null && (n < low || n > high)) {
      tf.setLocalColorScheme(GCScheme.RED_SCHEME);
    }
    return n;
  }

  public static Float Float(GTextField tf) {
    tf.setLocalColorScheme(GCScheme.BLUE_SCHEME);
    Float n = null;
    try {
      n = Float.parseFloat(tf.getText());
    }
    catch(NumberFormatException nfe) {
      tf.setLocalColorScheme(GCScheme.RED_SCHEME);
    }
    return n;
  }

  public static Float Float(GTextField tf, float low, float high) {
    Float n = Validate.Float(tf);
    if (n != null && (n < low || n > high)) {
      tf.setLocalColorScheme(GCScheme.RED_SCHEME);
    }
    return n;
  }
}

public void createGUI() {
  G4P.messagesEnabled(false);
  G4P.setGlobalColorScheme(GCScheme.BLUE_SCHEME);
  G4P.setMouseOverEnabled(false);
  G4P.setInputFont("Arial", G4P.PLAIN, 16);
  surface.setTitle("Validating number input");
  txf1 = new GTextField(this, 10, 20, 380, 30, G4P.SCROLLBARS_NONE);
  txf1.setPromptText("Enter an integer");
  txf1.setOpaque(true);
  txf1.addEventHandler(this, "txf1Change");
  txf2 = new GTextField(this, 10, 60, 380, 30, G4P.SCROLLBARS_NONE);
  txf2.setPromptText("Enter integer -50 to 100 incl");
  txf2.setOpaque(true);
  txf2.addEventHandler(this, "txf2Change");
  txf3 = new GTextField(this, 10, 100, 380, 30, G4P.SCROLLBARS_NONE);
  txf3.setPromptText("Enter any decimal number");
  txf3.setOpaque(true);
  txf3.addEventHandler(this, "txf3Change");
  txf4 = new GTextField(this, 10, 140, 380, 30, G4P.SCROLLBARS_NONE);
  txf4.setPromptText("Enter any negative number");
  txf4.setOpaque(true);
  txf4.addEventHandler(this, "txf4Change");
}
2 Likes

As per usual, amazing support and caring. Thank you so much Peter!!!

I will examine your suggestions and try them.

I appreciate your time and dedication.

We are similar. I am developing some music faders, and I leave no stone unturned to make them better. If someone makes a suggestion, I consider it carefully - it doesn’t always make sense to implement others’ suggestions. But sometimes it does.

Thank you again,

Mike

OK interesting…CONTROL + C and CONTROL + V works.

I’m on a Mac. COMMAND + C and COMMAND + V do not work…would be weird to tell folks they have to use the PC key on their Macs to cut/paste…

Still investigating your solutions; again thanks!

Mike

Hi Peter,

I’ve tried your validation scheme. It does work!

It’s really not ideal - better to have nothing input when they enter the wrong kind of data - but it is a workaround that I can use. Plus I’m assuming I can trap the error and prevent other actions from that point, by setting a flag etc.

I will make a more aggressive color theme for errors, thanks to your handy little guide on your website as to how to edit the color themes.

I can’t thank you enough for your kindness in helping a stranger.

I’m in Yorkshire area. If you’re ever close by, give me a shout and I’ll buy you a beer! At least you should have a donation button on your website. You deserve some renumeration for your efforts.

All my best!

Mike
Mike@musiotech.com

PS, I’m trying to learn Java…You have my admiration! I’m just getting into encapsulation and inheritance, and why not to set a mutable variable like an array equal to another…tricky stuff!

PPS -

So a question - I notice when trying the color scheme change code, it changes color to red when you click in the field, and stays red until you enter valid data.

Is there any way to have it stay on the blue scheme until someone enters wrong data?

**EDIT - think I’m figuring it out by using an if to check if the string is empty first before calling the validation class:

public void txf1Change(GTextField source, GEvent event) {
  if (txf1.getText() != "") Validate.Integer(source);
  println("text: '" + txf1.getText() + "'");
}
}

Apparently when you click a tf, it captures an empty string upon clicking the control…I’ll keep working with it.

Thanks again; great work kind sir!

Mike

In the validation example for numbers modify the event handlers like this

public void txf1Change(GTextField source, GEvent event) {
  if (event == GEvent.LOST_FOCUS)
    Validate.Integer(source);
  else if (event == GEvent.GETS_FOCUS)
    source.setLocalColorScheme(GCScheme.BLUE_SCHEME);
}

I am also using a mac so same experience here. G4P hooks into Processing’s event thread and implementing this would be too much work for minimal gain.

Whether you delete invalid input (i.e. empty text field) or not is down to personal preference. If the expectation is that the text field will display some lengthy text then it is better to go back to the text field and edit the incorrect text rather than start again from nothing.

2 Likes

Thank you for explaining, I really appreciate it.

I also appreciate the amended class code you provided. For free. Again.

Thanks Peter! You rock!

Mike