I'm trying to display text inside a rectangle which I have the dimensions of (x, y, width, and height). However, if the text's length is long enough to the point where the text would leak outside the rectangle, I want to instead display as many characters as possible in a single line, followed by ellipses (...). I am aware that I can use the Graphics.getFontMetrics().stringWidth(text) to get the width the text would occupy in pixels. I could use this method by looping through, adding a character at a time to the string that would be displayed and checking if its width exceeds the rectangle's width. However, this feels inefficient.
As such, I want to know if there is a better/efficient way of doing this.
Related
I want to center a block of text in a rectangle. I am currently using the PDFont.getStringWidth method for centering horizontally. However, I do not see a corresponding PDFont.getStringHeight method. Is there a way to get the height of a string, taking into account descenders? I see the getHeight method, but that would only work for a single character, and sounds like it would be expensive to call for a long string.
Screenshot for context
So I have created a little menu system that uses RectF for each button. This is mainly for persistant options, like inverting the accelerometer's X orY axis, or setting the number of dots displayed. The dimensions for the buttons are calculated using the screen size and orientation so that they look the same size on every device, and whichever orientation.
So since I have these rectangles defined, I would like to put text in them that is scaled to those rectangles. One way I thought of was to draw large text to a bitmap that is the hieght of the text bounds height of "Aq" and just wide enough for the text. With that, I could just scale the bitmap down to the size proportional to the recatngles. But I'm not sure it is the most efficient way of doing this. Is there some math for calculating the text size property (in the Paint object?) based on the dimensions of these rectangles so that I can just use DrawText to place the text over these rectangles? Or should I just use the bitmap idea?
Okay, so the text size is actually the height of the text, so I just gave it a size that is half the value of the height of the rectangle it was to be drawn in. Poof it's a perfect size every time. From there, I set the alignment on the text to centered, and placed drew the text at the center coordinates of the rectangle. I also had to add half of the size from the text to the texts y coordinate so the text would center.
canvas.drawText("Flip X Axis",myRect.centerX(),myRect.centerY()+ (textSize/2), myPaint);
Result
From an xml file, I'm given a width, height and id. All of them can and do vary very quickly. Now, I'm asked to draw a rectangle using the width and height (an easy task), and place the id at its center. The id must not overflow out of the rectangle it's contained it.
For single-character strings, this is also easy - set the font size to the height, play a bit with the x position maybe, and it's centered. The problem is when it's multi-character strings.
So given a width and height and a string, how can you determine what font-size the string should appear in? Assume you have every bit of information you need on the rectangle you're drawing the string in.
[Edit]: I'm using the Graphics 2D class to draw everything.
Start with selecting a Font at your preferred (i.e. maximum) size.
Grab the FontRenderContext from your Graphics2D object using getFontRenderContext.
Use getStringBounds() on the Font to be rendered to get a Rectangle2D object for the specific String to be rendered. That object describes the final size of the String using that Font
Check if the size specified by that Rectangle2D is small enough.
4a. If it is small enough, you're done. Use the last Font you've checked.
4b. If it is too big, use Font.derive() to produce a smaller version of the Font and continue to use that and loop back to 3.
Don't quite have the time to give you a full working example, but here are a couple pointers that should get you going in the right direction. The graphics object you are using to draw with has a getFontMetrics() method, one of the methods on FontMetrics is stringWidth(String str) which gives you the width of a string in the current Font.
If the width is too big for your rectangle set the Font on the Graphics object to the same font just with a smaller size until it fits.
To horizontally center a string in a container (learned long ago in typing class in high school):
(rectangleWidth / 2) - (stringWidth / 2)
http://download.oracle.com/javase/1.5.0/docs/api/java/awt/FontMetrics.html
To create a Font with a smaller size, something like:
Font font = graphics.getFont();
Font smallerFont = font.derive(font.getSize() - 1);
graphics.setFont(smallerFont);
Hope this gets you going in the right direction.
I would recommend for this problem to remove as many unknowns as possible. In this case, the problem chiefly is that font characters can vary in width... well most. That's why I would use a good monospace font like courier new for the ID, that way you know what the width of each character is, you know the width of your rectangle and you know the number of characters in your string. You can simply reduce the pixel size of each character will till your string fits the available width.
Example, if the width of each character is 12px and you have 10 characters in your ID, then you need 120px to fit everything in. If you only have 80px available, it's simple math 80/10 = 8px font-size (reduce half a pixel for padding if you want.
Just my suggestion.
Let's say a string rendered with a 10-point font is 200 pixels wide. If I draw the same string with a 15-point font (a 50% increase), will its rendered width also increase by 50% (to 300 pixels)?
(Of course, this assumes no other changes in the font and the Graphics2D where the text is rendered.)
In other words, is there a direct linear relationship between a font's point size and the size text is rendered? Or are there other variables that prevent me from making any such assumptions?
You're close with your assumption.
However, the spacing between letters doesn't always scale exactly. I believe it has to do with integer division sometimes having a remainder, but I haven't looked at the Java FontMetrics class code in a while.
You're safest always creating a new Font with the appropriate font size, and calling the getStringBounds method on the FontMetrics class.
So I've got an assignment that takes two inputs, males and females, and outputs matingPairs, the product of the two.
In addition to that, the instructions ask to draw a shape using one of those variables.
I've decided to draw circles for each value.
I first draw matingPairs, followed by the smaller male and female circles on top of the original, larger matingPairs circle.
The problem I'm running in to is obviously representing the graphic in the applet. If the numbers go higher than say 100, the graphic becomes too large for the applet.
I'm looking for a way to basically have the matingPairs circle always fill the applet, then have males and females dynamically adjust so their size is scaled relative to the matingPairs circle size. I'm using JApplet.
Thank you very much for any guidance. I'm really looking for a solution, rather a push in the right direction.
May be you should provide more instruction about how are you drawing the circles in the Graphics object.
The idea is to manage two bi-dimensional spaces with different scales; the first one is the input data and the second one represents the available area to draw such data. The first one can have data on any location, such (5, 5), (0.2, 0.3)or (1200, 3400). The key is to map the original coordinates of the first space into the second, using the proper transformation: scale + translation.
This transformation must be calculated prior to start drawing and applies to any point drawn.
The idea is to map the rectangle where input data resides to the available area in the graphics. If the graphics area is 200x200 pixels and the data could be from (0, 0) to (400, 400), just divide by 2 the coordinates of the points to draw. If the original data is not centered in (0, 0), use a translation.
So, do you need to know how to get the size of the applets canvas or how to scale the male/female circles accordingly?
Edit:
Drawing a circle to fill the 600x600 area should be easy. Just keep in mind that you often specify the top left corner of the circle and the width and height (i.e. the diameter) when calling drawOval() / fillOval() or similar methods.
The next question is: what does represent the size of the input (males/females) and output (pairs), the area or the radius of the circles? Whatever it is, it should be easy to calculate the input/output ratio and then multiply the fixed size of the output circle with it in order to get the size of the input circle.