I'm trying to fill a JPanel with a neat grid containing as many JLabels as will fit into the JPanel. The size of the JPanel can vary, and the size of the JLabels depends on the label text, the icon included in the JLabel, and the font being used to render the label text.
GridLayout myLayout = new GridLayout();
JPanel myPanel = new JPanel(myLayout);
List<JLabel> myLabels = ...
int panelWidth = myPanel.getWidth();
int panelHeight = myPanel.getHeight();
if (panelWidth == 0 || panelHeight == 0) return;
int maxLabelWidth = 0, maxLabelHeight = 0;
for (JLabel label : myLabels) {
int labelWidth = ???
int labelHeight = ???
if (labelWidth > maxLabelWidth) maxLabelWidth = labelWidth;
if (labelHeight > maxLabelHeight) maxLabelHeight = labelHeight;
}
// Use panelHeight, panelWidth, maxLabelHeight and maxLabelWidth to compute
// rows and columns available for myLayout
myLayout.setRows(nRows); myLayout.setColumns(nColumns);
for (JLabel label : myLabels) {
myPanel.add(label);
// stop if we reach nRows*nColumns labels
}
I've tried myPanel.getGraphics().getFontMetrics().getHeight() to get the height of text, but when the font is large and myPanel is small, the text is taller than labelHeight, and the bottom and top get cut off.
I've tried label.getIcon().getIconHeight() to get the height of the icon, but using this value always cuts off the top and bottom of the icons.
I've tried label.getSize() to get the height and width of the JLabel, but that usually returns 0 height and 0 width. I've tried label.getPreferredSize() but that generally returns a value that's too small.
I've tried label.getGraphics().getFontMetrics().stringWidth(label.getText()) to get the width of the string, and then added that to label.getIcon().getIconWidth() and label.getIcon().getIconTextGap() but that comes up with a value a little larger or smaller than label.getPreferredSize(), and in any case still too small - sometimes the label text is cut off at the end.
At one point I tried adding a constant to each width and height; that prevented cut-off text and icons, but of course it left too much blank space around the JLabels. Is there a way to get an accurate size for each JLabel for this usage?
Related
I know this has been asked a ton of times, but I've searched everywhere and still haven't found an answer. I'm relatively new to Java. I have
JButton b[][];
Later, I assign b[3][3].setIcon(path). However, the image at path is always a small section of the actual image the size of the JButton. What I want is to re-size the image to fit the size of the JButton. Is there any way to do this? By the way, here's some code that's (I think) is important:
int n = 8;
int m = 8;
...
b = new JButton[n][m];
setLayout(new GridLayout(n,m));
for (int y = 0;y<m;y++){
for (int x = 0;x<n;x++){
b[x][y] = new JButton(" ");
b[x][y].addActionListener(this);
add(b[x][y]);
b[x][y].setEnabled(true);
}
}
What I want is to re-size the image to fit the size of the JButton.
You can use the Stretch Icon class.
It will allow you to automatically resize the Icon:
to fill the space of the button, or
keep the Icon proportion and fill the space of the button
The resizing is done dynamically so you don't need scaled images.
What you obviously need is a Icon Resizer method, something in the way of what I have provided below:
public static Icon resizeIcon(ImageIcon icon, int resizedWidth, int resizedHeight) {
Image img = icon.getImage();
Image img = img.getScaledInstance(resizedWidth, resizedHeight, java.awt.Image.SCALE_SMOOTH);
return new ImageIcon(img);
}
You can call this method after the image has already been applied to the JButton and after it has been added to whatever panel:
b[3][3].setIcon(path)
b[3][3].setIcon(resizeIcon((ImageIcon) b[3][3].getIcon(),
b[3][3].getWidth() - 15, b[3][3].getHeight() - 15));
or you could do it this way:
ImageIcon img = new ImageIcon("MyImage.png");
Icon icn = resizeIcon(img, b[3][3].getWidth() - 15, b[3][3].getHeight() - 15);
b[3][3].setIcon(icn);
There were many posts regarding this problem, but i couldn't understand the answers given by people in there.
Like in this post: "How to change the size of the font of a JLabel to take the maximum size" the answer converts the font size to 14! But that is static and further in other answers; their whole output screen seems to increase.
I display certain numbers in a JLabel named "lnum", it can show numbers upto 3 digits but after that it shows like "4..." I want that if the number is able to fit in the label, it should not change its font size but if like a number is 4 digit, it should decrease the font size in such a way that it fits. NOTE: i do not want that the dimensions of the jLabel change. I just want to change the text in It.
Edit:
Here is what code i tried
String text = lnum.getText();
System.out.println("String Text = "+text);//DEBUG
Font originalFont = (Font)lnum.getClientProperty("originalfont"); // Get the original Font from client properties
if (originalFont == null) { // First time we call it: add it
originalFont = lnum.getFont();
lnum.putClientProperty("originalfont", originalFont);
}
int stringWidth = lnum.getFontMetrics(originalFont).stringWidth(text);
int componentWidth = lnum.getWidth();
stringWidth = stringWidth + 25; //DEBUG TRY
if (stringWidth > componentWidth) { // Resize only if needed
// Find out how much the font can shrink in width.
double widthRatio = (double)componentWidth / (double)stringWidth;
int newFontSize = (int)Math.floor(originalFont.getSize() * widthRatio); // Keep the minimum size
// Set the label's font size to the newly determined size.
lnum.setFont(new Font(originalFont.getName(), originalFont.getStyle(), newFontSize));
}else{
lnum.setFont(originalFont); // Text fits, do not change font size
System.out.println("I didnt change it hahaha");//DEBUG
}
lnum.setText(text);
I have a problem that many a times it doesn't work, like if the text is "-28885" it shows "-28...".
stringWidth = stringWidth + 25; //DEBUG TRY
I had to add this code so that it increases the length that it gets. It was a code i added to just temporarly fix the problem. I want a permanent solution for this.
Adapted from an answer on the question you referred to:
void setTextFit(JLabel label, String text) {
Font originalFont = (Font)label.getClientProperty("originalfont"); // Get the original Font from client properties
if (originalFont == null) { // First time we call it: add it
originalFont = label.getFont();
label.putClientProperty("originalfont", originalFont);
}
int stringWidth = label.getFontMetrics(originalFont).stringWidth(text);
int componentWidth = label.getWidth();
if (stringWidth > componentWidth) { // Resize only if needed
// Find out how much the font can shrink in width.
double widthRatio = (double)componentWidth / (double)stringWidth;
int newFontSize = (int)Math.floor(originalFont.getSize() * widthRatio); // Keep the minimum size
// Set the label's font size to the newly determined size.
label.setFont(new Font(originalFont.getName(), originalFont.getStyle(), newFontSize));
} else
label.setFont(originalFont); // Text fits, do not change font size
label.setText(text);
}
When you'll display a number that would fit, you should reset the Font back to its original (see the else part).
EDIT: If you can't/don't want to keep a reference to the original Font, you can save it as a "client property" (see the first lines).
I want to be able to do something similar to resize canvas in gimp
I want to generate a bunch of images to a certain width.
I used
int width = (int)(size * fraction);
int height =(int)(size*icon.getIconHeight()/icon.getIconWidth()*fraction);
miniature = new ImageIcon(i.getScaledInstance(width, height, Image.SCALE_SMOOTH));
this goes well while I'm doing fraction 1 but I have 3 images that have the same source but are different size (1, 2/3, 1/3)
the problem is
I have and image A
I want to create B, C and D such as the drawing inside respect the follow ratio
B = A
C = 2/3 A
D = 1/3 A
but the image stays the same dimension A = B = C = D
Assuming I'm following what you are trying to do...
Create a JLabel for each image:
JLable l = new JLabel(miniture);
Create a JLabel with a GridLayout:
JPanel p = new JPanel(new GridLayout());
Add the labels to the panel:
p.add(l);
The GridLayout will ensure that all the JLabels will have the same height and width.
I have a JLabel in a horizontally re-sizable JPanel. The JLabel auto re-sizes its width to fit the JPanel. If I insert a long line of text (such as "aaaaaaaaaaaaaaaaaaaaaaaa") the JLabel doesn't truncate the text. Instead, the width re-sizes to fit the text, causing also an ugly re-sizing of the JPanel.
Instead, I want my text to be truncated with an elipse (...). The JLabel width must not inherit from the text's length but only from the JPanel width.
Try following:
final JLabel label = ...
...
label.setText("prototype text to define size");
final Dimension size = label.getPreferredSize();
label.setMinimumSize(size);
label.setPreferredSize(size);
...
label.setText(...);
Use a different layout or set a max size on the JLabel.
You need to disable 'Horizontal Resizable' when you define a max- and preferedsize
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.