When the text in JLabel is too long there are visible 3 dots at the end of text. Is it possible to put them at the beginning?
-
don't know directly, not needed that, but a few times asked for XxxRenderer for longer description (by default there is JLabel as renderers Components) – mKorbel Oct 22 '13 at 14:01
-
@LittleChild this is a specification requirement, not my caprice – tobi Oct 22 '13 at 14:23
-
@tobi I have come up with a crazy answer. See if that helps. – An SO User Oct 22 '13 at 14:26
3 Answers
You may consider using FontMetrics
. class to see the length of your text under the current font.
_________________________________
|
| This is some really long text that I want to fit in the small label
|________________________________
^^^ YOUR LABEL ^^^
Say you want to fit that long text into that label.
Here is what you can do (and this is just a wild guess and I am making this on the fly)
- Start with your three dots
...
in aString
. - Start adding appending characters to it, one by one.
- Get the width of your
JLabel
. - Use
FontMetrics
to measure the length of your text , in pixels, as you append more characters - Keep adding more characters as long as the pixel length of the text is less than the width of your
JLabel
- Once it becomes greater than the width of the
JLabel
, get out of the loop. - Set this newly formed text as the text of your
JLabel
You should end up like this:
_________________________________
|
| ...This is some really long tex
|________________________________
^^^ YOUR LABEL ^^^
Here is an easy way to get started with FontMetrics
. Avoid the bickering there. Just do what the accepted answer says: Java: Friendlier way to get an instance of FontMetrics
SSCCE is in accordance with what the OP really wants rather than what I explained
package stack;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Toolkit;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class BackwardsDots extends JFrame{
JLabel label = new JLabel(){
@Override
public Dimension getPreferredSize(){
return new Dimension(200,100);
}
};
String text = "This is a design requirement and not my whim";
FontMetrics fm;
Font theFontBeingUsed;
//--------------------------------------------------------------------------------
public BackwardsDots(){
getContentPane().add(label);
pack();
theFontBeingUsed = new Font("Ubuntu",Font.BOLD,14);
fm = Toolkit.getDefaultToolkit().getFontMetrics(theFontBeingUsed);
label.setText(trimmedStringCalculator(text));
label.setToolTipText(text);
label.setBorder(BorderFactory.createDashedBorder(Color.RED));
label.addComponentListener(new ComponentListener(){
@Override
public void componentHidden(ComponentEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void componentMoved(ComponentEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void componentResized(ComponentEvent arg0) {
label.setText(trimmedStringCalculator(text));
}
@Override
public void componentShown(ComponentEvent arg0) {
// TODO Auto-generated method stub
}
});
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
//--------------------------------------------------------------------------------
private String trimmedStringCalculator(String inputText){
String ellipses = "...";
String textToBeDisplayed = "";
int widthOfJLabel = label.getWidth();
for(int i = text.length()-1; i >= 0; i--){
if(fm.stringWidth(ellipses + textToBeDisplayed) <= widthOfJLabel){
textToBeDisplayed = text.charAt(i) + textToBeDisplayed;
}
}
String finalText;
if(textToBeDisplayed.equals(inputText)){
finalText = inputText;
}else{
finalText = ellipses.concat(textToBeDisplayed);
}
return finalText;
}
//--------------------------------------------------------------------------------
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
new BackwardsDots();
}
});
}
}
Output

- 1
- 1

- 24,612
- 35
- 133
- 221
-
2From what I understand from the OP, I think he wants something like `... fit in the small label`. That would make a bit more sense. – Mickäel A. Oct 22 '13 at 14:30
-
It's not the way I wanted it to be. In my case it should print something like: "...want to fit in the small label" – tobi Oct 22 '13 at 14:32
-
Start with the `...`. Create a new `String` called `textTobeDisplayed` and iterate backwards i.e. from the end of the text, moving towards the start. Append the characters to the start of the `textToBeDisplayed` and measure total length i.e. length of `...` plus `textToBeDisplayed` =) – An SO User Oct 22 '13 at 14:34
-
-
-
@trashgod I am aware of it but I was just trying to get the point across. =) – An SO User Oct 22 '13 at 19:41
I have another solution, that relies on LabelUI. First the code:
LabelUI labelUI = new MetalLabelUI() {
@Override
protected String layoutCL(JLabel label, FontMetrics fontMetrics, String text, Icon icon, Rectangle viewR, Rectangle iconR, Rectangle textR) {
String clipString = "...";
// Use reversed text, because first characters may be larger or thinner than last ones.
String reversedText = new StringBuilder(text).reverse().toString();
// Let Swing do its magic.
String result = super.layoutCL(label, fontMetrics, reversedText, icon, viewR, iconR, textR);
// Not using .equals is intentional. Previous method will return a different instance
// if and only if a clip operation occurred.
if (result != text) {
// Use the same character count, but starting with the end.
result = clipString
+ text.substring(text.length() - result.length() + clipString.length());
} else {
// Restore the original
result = text;
}
return result;
}
};
The goal is to let Swing compute everything, including its clipped string, and using this as a hint to perform our own left clipping. The trick is that we have to provide the reversed string to the super method, since our result will clip leading characters, we need to be sure that the computation was right. Characters have different widths.
The main advantage for me is that there is a very little overhead, compared to the current solution that compute a new size before the UI, and the UI will start doing the same.
EDIT: Change code to restore the original string when not clipped.

- 2,636
- 1
- 21
- 26
-
2Nice answer, thanks ;). Though this can actually be done even simpler: the LabelUI itself will append the dots, so simply handing the reversed `String` to `super.layoutCL(...)` and afterwards reversing again can do the trick as well, without any conditionals or string-manipulation. – Dec 30 '16 at 22:56
I think this is rather a system behaviour, more than JLabel
's, so you couldn't really do that.

- 3,513
- 2
- 31
- 49