I have a Label object with a text in it...
Label label = new Label(text);
..and I get the height by...
label.pack();
GlyphLayout layout = label.getGlyphLayout();
float height = layout.height;
When I add them to a table I just said
Table t = new Table();
t.add(label).width(200).height(height);
Currently I work on a chat window and each entry of the
window is a Label containing a colored name and text, like...
Note: The debug lines are drawn. Please ignore the blue line, it's from another table in the scene
Now my question: The 1-liner has a glyphlayout height of 38 and the 3-liner 139. Does someone know why there's such a big gap between the 2 entries resp. why the 3-liner height doesn't seem to be correct? No extra spacing / padding.
I would appreciate any ideas to solve this.
SOLVED:
My post was incomplete, sorry. I set the width of the label before calling...
label.setWidth(x); // where x was < chatbox width
label.pack();
So the GlyphLayout assumed a width which was smaller than the actual chatbox width. The result is of course a bigger height...
Thanks a lot to the libgdx IRC, especially Tomski :)
Related
I have a table like this:
All what I want is to align easy, medium and hard texts in the middle of the cell, at least horizontally.
I searched a lot on how to do this, but I didn't find anything useful...
My code for the table is this:
table.setBounds(0, 0, Info.Width, Info.Height);
table.row();
table.add(label).expandX().colspan(3);
table.row().padTop(20).width(Info.Width);
table.add(easyText).width(Info.Width / 3).expandX();
table.add(mediumText).width(Info.Width / 3).expandX();
table.add(hardText).width(Info.Width / 3).expandX();
table.row().padTop(10);
table.add(easyHighscoreLabel).width(Info.Width / 3);
table.add(mediumHighscoreLabel).width(Info.Width / 3);
table.add(hardHighscoreLabel).width(Info.Width / 3);
table.row().padTop(50);
table.add(backButton).expandX().colspan(3);
Info.Width, Info.Height are the width and the height of the app.
label is the title: "HIGHSCORES".
easyText, mediumText, hardText are the texts I want to align.
easyHighscoreLabel, mediumHighscoreLabel, hardHighscoreLabel, are the numbers below the text.
And backButton is "Back" from bottom.
Use setAlignment (int alignment) on your label by default it is left center.
easyText.setAlignment(Align.center);
mediumText.setAlignment(Align.center);
hardText.setAlignment(Align.center);
This will align all the text by center within the label.
I have a set of custom made "buttons" for the menu screen of my game. It's basically a StackPane with a Rectangle and a Text node stacked. Basically this is similar to how my buttons are structured.
Pane button1 = new StackPane(new Rectangle(100, 50), new Text("Play!"));
Pane button2 = [....];
Then I insert buttons into a VBox and into my menu along with a header text:
VBox buttons = new VBox(button1, button2, button3...);
Pane menuScreen = new BorderPane(buttons, new Text("The Game"), null, null, null);
However, for my custom detection for mouse position compared to the buttons I need to know the buttons' positions...
int x = button1.getLayoutX(); //returns 0
int x = button1.getTranslateX(); //returns 0
int x = button1.localToScene(0, 0).getX(); //returns 0
int x = button1.localToScene(buttons.get(0).getBoundsInLocal()).getMinX(); //returns 0
int x = button1.localToScene(buttons.get(0).getBoundsInLocal()).getMaxX(); //returns the width of the entire scene
int x = buttons.get(0).getTranslateX(); //returns 0
int y = button1.localToScene(buttons.get(0).getBoundsInLocal()).getMinY();
The last case returns 234.0 if I have the VBox set with .setAlignment(Pos.CENTER) and 64.0 if I don't. But for .getMinX() it stays at 0.0 in either case. I believe it's related to the BorderPane's left/right/bot regions being set to null while the top region has the title text.
I cannot find any way of getting the x coordinate when the buttons are in a layout pane other than the Pane class itself. I tried StackPane as well. My suspicion is that there is no fixed coordinate and that properties are involved, but I only get confused from reading about it when I don't know what I'm looking for.
I have tried solutions from this quesion and this seems to be the same but as I mentioned I'm afraid my minX() doesn't have a set value since the VBox is the only thing filling the center row of my BorderPane.
Edit: StackPane seems to give the right values for .getMinX() when I use .setAlignment(Pos.CENTER), but I am not allowed to do that with the text, only with the VBox, so then the text gets stuck on top of the buttons.
My issue was cause by the VBox and my StackPanes taking up all the possible space, not just the area of the visible Rectangle. Problem was solved by calling setMaxWidth(100) on the StackPane which contained the Rectangle and the Text.
Also, the only problem seems to be that you have a zero x-coordinate. Maybe this is "real". Set a background on button1 to see where it is in the layout. – James_D
Okay, so I have this.
calibri.draw(FBLA_Game.spriteBatch, "Rooftop Defender",0 ,0 );
Anyways, this code... I need the text to be centered. Instead of the 0's, I would have it like this:
calibri.draw(FBLA_Game.spriteBatch, "Rooftop Defender",Gdx.graphics.getWidth()/2 ,Gdx.graphics.getHeight()/2 );
But this isn't what I want. this centers the beginning of where it writes the words. So then for the width I would need to subtract the width of the word being written, But I cannot figure out how to get the width of "Rooftop Defender" that is being written.
Thanks for any and all help,
Alex
In new versions (>1.6) of LibGDX BitmapFont is being handled with GlyphLayout class which you can use to calculate the future width of your rendered string
//out of render() method! this call is expensive
GlyphLayout glyphLayout = new GlyphLayout(calibri, "Rooftop Defender");
...
//render()
float glyphLayoutWidth = glyphLayout.width;
We have an app that draws text, but then displays a JTextArea for the user to edit the text when they click on the text. However, the wrapping between these two text-handling components differs. They use the same width, text String, and Font.
For the text-drawing, I'm using the from the Java tutorial, which I've also seen used by others in related questions here and other forums. Here's that part of the code:
FontRenderContext frc = g2d.getFontRenderContext();
TextLayout layout;
AttributedString attrString = new AttributedString(myText);
AttributedCharacterIterator charIterator;
int paragraphStart;
int paragraphEnd;
LineBreakMeasurer lineMeasurer;
float breakWidth;
float drawPosX;
float drawPosY;
attrString.addAttribute(TextAttribute.FONT, myFont);
charIterator = attrString.getIterator();
paragraphStart = charIterator.getBeginIndex();
paragraphEnd = charIterator.getEndIndex();
lineMeasurer = new LineBreakMeasurer(charIterator, frc);
// Set break width to width of Component.
breakWidth = myTextWidth;
drawPosY = startY
// Set position to the index of the first character in the paragraph.
lineMeasurer.setPosition(paragraphStart);
textBounds = new Rectangle(startX, startY(), 0, 0);
// Get lines from until the entire paragraph has been displayed.
while (lineMeasurer.getPosition() < paragraphEnd) {
layout = lineMeasurer.nextLayout(breakWidth);
// Compute pen x position. If the paragraph is right-to-left we
// will align the TextLayouts to the right edge of the panel.
drawPosX = layout.isLeftToRight()
? startX() : breakWidth - layout.getAdvance();
// Draw the TextLayout at (drawPosX, drawPosY).
layout.draw(g2d, drawPosX, drawPosY);
lineBounds = new Rectangle2D.Float(drawPosX, drawPosY - layout.getAscent(), layout.getAdvance(), (layout.getAscent() + layout.getDescent() + layout.getLeading()));
// Move y-coordinate in preparation for next layout.
drawPosY += layout.getAscent() + layout.getDescent() + layout.getLeading();
}
The JTextArea is much simpler:
JTextArea textArea = new JTextArea(myText);
textArea.setSize(myTextWidth, myTextThing.getHeight());
textArea.setOpaque(true);
textArea.setVisible(true);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.setFont(myFont);
textArea.setBorder(null);
I set the border to null because I have another rectangle drawn outside the bounds of the text area with a dashed area to show where it is. Might seem silly now, but we use it to show the bounds of the text area when the user first selects the text they want to edit. At that point, the JTextArea isn't yet created. They have to click on it again to begin editing. The reason for this is that once a text area is selected, they may also drag and resize the text area, and that gets messy and more confusing if they had a live JTextArea when they started dragging and resizing.
Separately, both the drawn TextLayouts and the JTextArea appear to wrap words just fine. but when used together you can see the difference. The problem with this is that while the user is editing the text, the JTextArea is doing its thing to wrap the text. But when the user JTextArea loses focus, it is converted to the drawn text, and then the words may be wrapped differently.
Fill the text area with i or l characters. Grab a UI ruler or magnifying glass and count the size of your text area in pixels from the leftmost character of the longest line to the rightmost. Do the same with n, m, and a few other characters for a few more data points. I suspect that the text area has an invisible border of a few pixels it uses even when set to no border. If this is the case, add the same border around the TextLayout component and they should appear identical.
(Alternatively to counting pixels, you could set a background color for the text or the components, but I wouldn't necessarily trust it.)
I set my JPanel to GridLayout (6,6), with dimension (600,600)
Each cell of the grid will display one pictures with different widths and heights.
The picture first add to a JLabel, and the JLabel then added to the cells.
How can retrieved the coordinate of the pictures in the cells and not the coordinate of cells? So far the out give these coordinate which equal height and width even on screen the pictures showed in different sizes.
e.g.
java.awt.Rectangle[x=100,y=100,width=100,height=100]
java.awt.Rectangle[x=200,y=100,width=100,height=100]
java.awt.Rectangle[x=300,y=100,width=100,height=100]
The reason why I used GridLayout instead of gridBagLayout is that, I want each pictures to have boundary. If I use GridBagLayout, the grid will expand according to the picture size.
I want grid size to be in fix size.
JPanel pDraw = new JPanel(new GridLayout(6,6));
pDraw.setPreferredSize(new Dimension(600,600));
for (int i =0; i<(6*6); i++)
{
//get random number for height and width of the image
int x = rand.nextInt(40)+(50);
int y = rand.nextInt(40)+(50);
ImageIcon icon = createImageIcon("bird.jpg");
//rescale the image according to the size selected
Image img = icon.getImage().getScaledInstance(x,y,img.SCALE_SMOOTH);
icon.setImage(img );
JLabel label = new JLabel(icon);
pDraw.add(label);
}
for(Component component:components)
{
//retrieve the coordinate
System.out.println(component.getBounds());
}
EDITED: I have tried this but not working :-(
for(Component component: pDraw.getComponents()){
System.out.println(((JLabel)component).getIcon());
}
How can I get output like these?
java.awt.Rectangle[x=300,y=100,width=50,height=40]
java.awt.Rectangle[x=400,y=400,width=60,height=50]
Do your images appear at the desired size ?
i think so.
Anyway, from what your code seems to do, I guess it gets the labels size, and not the icons size. JLabel, like any JComponent, are in fact Container instance. As such, their size depends upon constraints. As a consequence, in a GridLayout, a JLabel will have the size of a cell, whereas the contained Icon will have the size of the image.
As a consquence, to get image size, you have to call ((JLabel) component).getIcon() to be able to retrieve effective image dimension.