Get the amount of characters in one line of a textbox

Hey! Right now I'm making a test in Processing, and half of it involves a prompt on screen to answer questions from. Right now it looks like this.

Because I can't fit all the text of the prompt on screen with a reasonable font, I'm instead allowing the ability for the tester to scroll down and up the text. Here's a standalone example of what it would be like :

String originalText = "Happy birthday to you\n" + 
                      "Happy birthday to you\n" +
                      "Happy birthday Dear Random User\n" +
                      "Happy Birthday to you.\n\n" +

                      "From good friends are true,\n" +
                      "From old friends and new,\n" +
                      "May good luck go with you,\n" +
                      "And happiness too.";
String displayText;
int scrollAmount;
PFont font;
float scrollMultiplier;

void setup() {
  size(800, 800);
  displayText = originalText;
  font = createFont("Arial", 35);  
  scrollMultiplier = 30;
}

void draw() {
  background(0);
  fill(255);
  textFont(font);
  text(displayText, 40, 40, 700, 600);

}

void mouseWheel(MouseEvent event) {
 float value = event.getCount();
 scrollAmount += (int) value * scrollMultiplier;
 scrollAmount = constrain(scrollAmount, 0, originalText.length());
 displayText = originalText.substring(scrollAmount, originalText.length());
}

This is most of what I need. However, I want it so the user scrolls line by line instead of what it is right now where the lines kinda shift around since I'm splicing at random places in the substring.

What I need is to get the amount of characters of a certain line on screen and have this be the amount mulitplied by e in the mouseWheel method (essentially set the amount of characters to scrollMultiplier). This way it adds or subtracts an entire line of text instead of an arbitrary 30. The problem is ... I have no idea how to do this. I'm using the text option that takes four parameters as a box, with the specific line being

I'm not even sure if what I want is possible :| I can't just take the normal amount of characters that fit in a line since some are bigger than others and sometimes a line breaks midway to start a new paragraph. In short, I just need to get the amount of characters that are present on a certain line and have this value for scrolling purposes.

Thanks!

Answers

  • if (scrollCount < 0)
      scrollCount = 0;
    else if (scrollCount > prompt.length())
      scrollCount = prompt.length();
    

    Two things about this. Always use {} around blocks even if they are 1 line long, don't just rely on indentation because that's prone to hiding bugs (especially on a forum like this that does a bad job of indenting code).

    And secondly you can replace this with a call to constrain()

    Runable examples are preferred.

  • Look at String and there length()

    Also textWidth

  • edited August 2017

    @ koogs :( I love to minimize the curly braces, makes it look so much cleaner. Woe is me. Anyways I did fix the code so now it's just scrollCount = constrain(scrollCount, 0, prompt.length()); instead of the if statements. Thanks, I didn't know the command existed.

    I edited my original post with a standalone example.

  • edited August 2017

    @Chisir I'm not really sure how I could use those. textWidth outputs the same number no matter where the text breaks, and length() is just the string's length of characters

    -EDIT- I was wrong about textWidth, but I'm still unsure how I could use this to solve my problem.

    I attempted to use this on the example in my main post except I removed all the \n's

    void findIndexAmount() {
     for (int i = 1; i < 300; i++) 
      if (textWidth(displayText.substring(0, i)) > 700) {
        scrollMultiplier = i;
        break;
      }
    }
    

    Essentially it starts form the start of the line, finds the textWidth of it, and keeps adding a new character until the textWidth is as large as the text box width. This doesn't work on a full line since I guess a line that fits almost all the way but doesn't will be moved down but Processing will continue to check as if it wasn't moved down, and this wouldn't work at all then in the case of new lines.

    /.\ Yikes what a mess. I'm not sure if there is a solution. Not sure what I could do as an alternative either

  • Are you talking about the text to prompt the user with or the text that the user enters?

    I guess it's the former.

    Nothing special here. Just parse your long text into an array using split \n or whatever.

    Then check the length of each item / line in the array

    If it's too long insert the 2nd half into the array (using splice I think)

    When you're done, display the array

  • edited August 2017

    The user isn't entering any text, it's a prompt on screen like this. So yes the former.

    The example string probably wasn't the best. For the actual text I want to get to work in my program there is no \n's so I can't parse through them. I get the texts from a csv file, where the text looks like this.

    Sometimes it breaks into a new line, other time the string of text is too long for the textbox in Processingg so it wraps around to the next line.

  • My suggestion is still valid. Just extend a section at start of string until it's too long

    Go back to a stop char which is point, comma, ! ? or space.

    First section goes into array slot 1

    Remove slot from initial string

    Repeat

  • edited August 2017 Answer ✓

    Possibly also relevant -- approaches to word-by-word text layout (which is used for bold / color in the examples, but could be used for flow control).

    https://forum.processing.org/two/discussion/comment/87679/#Comment_87679

    An alternate hack: consider drawing a text box into a PGraphics, then rendering onto screen space. Scrolling moves the text box offset. This wouldn't work with 20 or 30 pgs of text, but it should work fine if you have 1-3.

  • Oh my goodness thanks @jeremydouglass so much! I didn't know PGraphics was a thing and is wayyyyyy better than this subtext stuff since it feels so much smoother. I can't thank you enough :) it's the literal perfect answer!

    Here's an example using it if you're curious

    PGraphics prompt;
    String promptText = "FlYle HQXNR \n zVCRN NMgdt nQfUZ NjapD\n LYuiD YeDgV fIbbi/n" +
                        "XmpxQ\n HLskH PyQBr ZpXQ\n NsIUY mfBXB\n ZdDuO\n qupdO EBIHx/n" +
                        "CwgRD\n saDIx gxusI HDZgT\n bmgcu kPSTU\n GoUnZ REUKV YFaMO CZwoS qIOWP" +                   
                        "neQUU fZxnq kJxrX\n tVZOH ZbwOV\n dqjuF CioeV\n OyNBu";
    String displayText;
    PFont font;
    int scrollCount;
    float scrollMultiplier;
    
    void setup() {
     size(400, 400);
    
     prompt = createGraphics(width, height);
     font = createFont("Arial", 18);
     prompt.beginDraw();
     prompt.textFont(font);
     prompt.endDraw();
    
     scrollMultiplier = 30;
     displayText = promptText; 
    }
    
    void draw() { 
     background(0);
    
     prompt.beginDraw();
     prompt.background(0);
     prompt.text(promptText, 0, scrollCount, width, height);
     prompt.endDraw();
    
    
     image(prompt, 0, 0);
    }
    
    void mouseWheel(MouseEvent event) {
     float e = event.getCount();
     scrollCount += (int) -e * scrollMultiplier;
     scrollCount = constrain(scrollCount, -height, height);
    }
    
  • Really glad it was helpful, @Dinoswarleafs -- and thanks for sharing your example!

Sign In or Register to comment.