Solved

Drawing multiline text inside a rectangle

Posted on 2007-11-29
13
4,700 Views
Last Modified: 2008-02-01
Hi,

Can anyone point out how to draw a really long string into a rectangle such that it auto breaks on words and wraps around? I have a rectangle I want to dump the text into, so I need something like:

public void DrawIntoRect(String str, Rectangle rc)
{
     // Let the string wrap when necessary, breaking between words, using the current font.
     // If there isn't enough space, finish off with a word ellipsis?
     drawString(str, rc);
}

In win32 there are some flags you can use to do this, what is there that we can use in java?
0
Comment
Question by:DJ_AM_Juicebox
  • 7
  • 3
  • 3
13 Comments
 
LVL 92

Expert Comment

by:objects
ID: 20379257
use a text area instead of painting it yourself.
If you're doing the painting yourself then you'll have to break the lines manually.
0
 
LVL 92

Expert Comment

by:objects
ID: 20379294
0
 
LVL 25

Expert Comment

by:InteractiveMind
ID: 20379299
As far as I know, there is no pre-existing method which does this for you.
Below I've written up an attempt at a custom method to do the job; I haven't tested it (am off to bed in a minute), but I think at least the idea is there.

(If it doesn't work, and the problem hasn't been resolved by the morning (GMT), then I'll test it out)
Font F=...;

FontMetrics FM=getFontMetrics(F);
 

public void DrawIntoRect(String str, Rectangle rc, Graphics g)

{

   g.setFont(F);

   int lineSep=3;

   int strWidth=FM.stringWidth(str);

   int strHeight=FM.getHeight();

   int strLength=str.length();

   int charPerLine=(int)(strLength*rc.width/(double)strWidth);

   if(charPerLine>=strLength)

      g.drawString(str,rc.x,rc.y+strHeight);

   else

   {

      int lines=strLength/charPerLine;

      int skip=0;

      for(int i=1; i<=lines; i++)

      {

         String sTemp=str.substring(skip,skip+charPerLine-1);

         if(!str.substring(skip+charPerLine-1,skip+charPerLine).equals(" ")&& !str.substring(skip+charPerLine-2,skip+charPerLine-1).equals(" "))

         {

            sTemp+="-";

         }

         g.drawString(sTemp,rc.x,rc.y+i*strHeight+(i-1)*lineSep);

         skip+=charPerLine;

      }

      g.drawString(str.substring(skip,strLength),rc.y+lines*strHeight+(lines-1)*lineSep);

   }

}

Open in new window

0
 
LVL 92

Expert Comment

by:objects
ID: 20379322
functionality is already avail in text components :)
0
 

Author Comment

by:DJ_AM_Juicebox
ID: 20379339
@objects:
But can you change the color of the background of the text component, and modify the font? I could use it if it 'appeared' as if it were painted by me.

@InteractiveMind:
I had to do the same thing in C++  a while back, this should me,

Thanks
0
 
LVL 92

Expert Comment

by:objects
ID: 20379359
> But can you change the color of the background of the text component, and modify the font?

absolutely, you can even apply whatever styles you want by using a JTextPane.
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 25

Accepted Solution

by:
InteractiveMind earned 500 total points
ID: 20381639
Certainly, if using an existing text component is a viable solution, then use that.
It's just that I've had cases in the past where I've had to do this, but could not use a text component (it was for a game engine).

So, I've corrected the above code, and have posted it below. This is for the benefit of others who may have the same requirements (but cannot use a text component).

(No points for me)
Font F=...;

FontMetrics FM=getFontMetrics(F);
 

public void DrawIntoRect(String str, Rectangle rc, Graphics g)

{

   g.setFont(F);

   int lineSep=3;

   int strWidth=FM.stringWidth(str);

   int strHeight=FM.getHeight();

   int strLength=str.length();

   int charPerLine=(int)(strLength*rc.width/(double)strWidth);

   if(charPerLine>=strLength)

      g.drawString(str,rc.x,rc.y+strHeight);

   else

   {

      int lines=strLength/charPerLine;

      int skip=0;

      for(int i=1; i<=lines; i++)

      {

         String sTemp=str.substring(skip,skip+charPerLine-1);

         if(!str.substring(skip+charPerLine-1,skip+charPerLine).equals(" ")&& !str.substring(skip+charPerLine-2,skip+charPerLine-1).equals(" "))

         {

            sTemp+="-";

         }

         g.drawString(sTemp.trim(),rc.x,rc.y+i*strHeight+(i-1)*lineSep);

         skip+=charPerLine-1;

      }

      g.drawString(str.substring(skip,strLength).trim(),rc.x,rc.y+(lines+1)*strHeight+(lines)*lineSep);

   }

}

Open in new window

0
 

Author Comment

by:DJ_AM_Juicebox
ID: 20382631
@InteractiveMind:
It seems to work, thanks!

@objects:
Same question as in other html post - if I use the text area object, can I just stick it above the device context of my applet? I mean the whole applet dimensions are part of my drawing context, so if I just stick this panel on top of a portion of it, what effect will it have? Will it start flickering everytime I repaint?

Thanks
0
 
LVL 92

Expert Comment

by:objects
ID: 20386662
you can place it whereeve you want in your component hierarchy.
it shouldn't flicker.
0
 
LVL 25

Expert Comment

by:InteractiveMind
ID: 20386712
(So long as you're using Swing, then it shouldn't flicker - as it has double-buffering built in, from what I remember)
0
 

Author Comment

by:DJ_AM_Juicebox
ID: 20388608
In all the examples I find about text panels, the main class looks like:

    public class TextDemo extends JPanel implements ActionListener

but I don't derive from JPanel, I derive from:

    java.applet.Applet implements Runnable

Can I still use the text panel?
0
 
LVL 92

Expert Comment

by:objects
ID: 20389412
yes, you can use whatever components you want. They are all derived from Component.
0
 
LVL 92

Expert Comment

by:objects
ID: 20389415
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Unable to open debugger port in Intellij idea 6 143
recursion example 16 111
rhino JavaScript import, load 25 67
split string containing \r\n in Java 46 38
For customizing the look of your lightweight component and making it look lucid like it was made of glass. Or: how to make your component more Apple-ish ;) This tip assumes your component to be of rectangular shape and completely opaque. (COD…
Introduction This article is the first of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article explains our test automation goals. Then rationale is given for the tools we use to a…
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:
Viewers will learn about basic arrays, how to declare them, and how to use them. Introduction and definition: Declare an array and cover the syntax of declaring them: Initialize every index in the created array: Example/Features of a basic arr…

910 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now