?
Solved

How to make a JLabel proportionally change size to fit a given string?

Posted on 2005-04-05
24
Medium Priority
?
4,823 Views
Last Modified: 2013-11-23
HI, Dear All:

I need to create a JLabel derived class that can accept a text string in its constructor to create a JLabel

Public class MyLabel extends JLabel {

//Constructor accept a text string
 MyLabel(String text){
        super();
        int lgth=text.length() * 10;
         setBounds(1,1,lgth,20);
        setText("text");
        setForeground(Color.black);
        setOpaque(true);
        setBackground(Color.red);
        setHorizontalAlignment(CENTER);
        setBorder(BorderFactory.createLineBorder(Color.black));
       }
     ...
}
         
Notice in the above code, I have to calculate the length of the given string and then use setBounds(1,1,lgth,20) to make it visible and sort of fit the text string into JLabel. I also add the JLabel component to a JPanel. My questions are:
1. Why I need setBounds to make it visible (Not visible if I take out the setBounds())
2. Is there anyway to make a JLabel (automatically if will) proportionally change size to fit a given string? (of couse with the default font and font size)? So that I do not have to calculate the length of the text string and use setBounds()

Alternatively, if JLabel can not do the No.2, is there any other component can have this feature?

Thanks a lot,

yi02

0
Comment
Question by:yi02
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 7
  • 6
  • +1
24 Comments
 
LVL 37

Expert Comment

by:zzynx
ID: 13708164
>> Why I need setBounds to make it visible
What's the layout of your JPanel?

>> Is there anyway to make a JLabel (automatically if will) proportionally change size to fit a given string?
That's the standard behaviour of JLabel.
But the used layout (manager) can decide not to show the JLabel in full length
0
 
LVL 14

Expert Comment

by:StillUnAware
ID: 13708177
Can't you after changing the label text, repack the panel, and refresh the swing
0
 
LVL 37

Expert Comment

by:zzynx
ID: 13708201
Try having a JFrame containing a JPanel (having the FlowLayout) containg a JLabel.
You'll see that the width of the JLable will be adapted to the length of the containing string.
(as long as it is not wider than the JFrame)

0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 37

Assisted Solution

by:zzynx
zzynx earned 400 total points
ID: 13708261
Consider this little demo app.
Run it and press the button and see the label adapt.

/*
 * LabelTest.java
 *
 */

import javax.swing.*;

/**
 *
 * @author  zzynx
 */

public class LabelTest extends javax.swing.JFrame {
   
    public LabelTest() {
        initComponents();
    }
   
    private void initComponents() {
        thePanel = new javax.swing.JPanel();
        theLabel = new javax.swing.JLabel();
        jPanel2 = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();

        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                exitForm(evt);
            }
        });

        theLabel.setText("Test");
        thePanel.add(theLabel);

        getContentPane().add(thePanel, java.awt.BorderLayout.CENTER);

        jButton1.setText("jButton1");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        jPanel2.add(jButton1);

        getContentPane().add(jPanel2, java.awt.BorderLayout.SOUTH);

        pack();
    }

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
        theLabel.setText("This is a very long text to test");
    }

    private void exitForm(java.awt.event.WindowEvent evt) {
        System.exit(0);
    }
   
    public static void main(String args[]) {
        LabelTest frame = new LabelTest();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500,500);
        frame.setLocationRelativeTo(null);
        frame.show();
    }
   
    // Variables declaration - do not modify
    private javax.swing.JButton jButton1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JLabel theLabel;
    private javax.swing.JPanel thePanel;
    // End of variables declaration
   
}
0
 
LVL 14

Expert Comment

by:StillUnAware
ID: 13708439
//As you can see this JLabel is dinamic

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;

public class C extends JFrame {
  JPanel panel = new JPanel();
  JLabel label = new JLabel("Edit the text below");
  JTextField jtf = new JTextField("Text to change Label text");
  C() {
    label.setBorder(new LineBorder(Color.BLACK));
    panel.setLayout(new FlowLayout());
    panel.add(label);
    jtf.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent ae) {
        String txt = ((JTextField)ae.getSource()).getText();
        label.setText(txt);
        ((JTextField)ae.getSource()).setText("");
      }
    });
    setLayout(new BorderLayout());
    add(panel, BorderLayout.CENTER);
    add(jtf, BorderLayout.SOUTH);
    pack();
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);
  }
  public static void main(String[] args) {
     C c = new C();
  }
}
0
 
LVL 14

Expert Comment

by:StillUnAware
ID: 13708446
sorry, too late to refresh
0
 

Author Comment

by:yi02
ID: 13708923
Dear zzynx:
to your question:
What's the layout of your JPanel?
I used
setLayout(new FlowLayout(FlowLayout.LEFT));
for my JPanel.
I did have JFrame to contain the JPanel, the backbone code is as below:

Public myFrame extends JFrame{
//Constructor
  public myFrame() {  
             
      super("My Frame");  // Call the constructor from the superclass,  
      MyCanvas canvas = new MyCanvas();
       setContentPane(canvas);
       canvas.setVisible(true);
......
     setLocation(0,0);
     setSize(750,600);
      show();
     }
}

Public MyCanvas extends JPanel {
MyCanvas() {
          super();
         setBackground(Color.white);
         addMouseListener(this);
         addMouseMotionListener(this);
         setLayout(new FlowLayout(FlowLayout.LEFT));
......
    }
     
    void AddGeneLabel() {
            //add JLabel to the JPanel      
      MyLabel myLB=new MyLabel("MyLongTextString");
      this.add(myJB);
      repaint();
      //pack(); If I add this line, the whole JPanel shrink to just hold the JPanel ,why is that?how to overcome?
   }
}

Public class MyLabel extends JLabel {

//Constructor accept a text string
 MyLabel(String text){
        super();
       // int lgth=text.length() * 10; if these two lines took out, then JLabel not visible
        // setBounds(1,1,lgth,20); but with pack() it did work, but got another problem, see code please!
        setText("text");
        setForeground(Color.black);
        setOpaque(true);
        setBackground(Color.red);
        setHorizontalAlignment(CENTER);
        setBorder(BorderFactory.createLineBorder(Color.black));
       }
     ...
}


After look at your code, I did try to add the pack() inside the AddGeneLabel() function, but the whole JPanel is shrink to fit the JLabel, how can I overcome this? I try setSize(), which has no effects. But I can manually expand the JPanel when running the program, how can overcome this?

Thanks a lot

yi02
0
 
LVL 14

Assisted Solution

by:StillUnAware
StillUnAware earned 400 total points
ID: 13708987
You may set the myFrame layout to BorderLayout, set it's size to any You like, and add the myCanvas as myFrame.add(canvas, BorderLayout.CENTER); instead of setContentPane(canvas);
0
 

Author Comment

by:yi02
ID: 13709173
Dear STillUnAware:

I did what you suggested, it works for the JLabel , but encountered the same problem: The whole JPanel and JFrame shrinked to just hold the JLabel. How can I reset the window size to its original one?

Thanks a lot.

yi02
0
 
LVL 92

Expert Comment

by:objects
ID: 13714249
try:

    void AddGeneLabel() {
            //add JLabel to the JPanel      
      MyLabel myLB=new MyLabel("MyLongTextString");
      this.add(myJB);
      revalidate();
      repaint();
   }
0
 
LVL 37

Expert Comment

by:zzynx
ID: 13714335
>> //pack(); If I add this line, the whole JPanel shrink to just hold the JPanel,
>> why is that?
Well, as the name of the function indicates, it packs ("shrinks", "compresses",...) the frame to its minimal form.
0
 
LVL 92

Expert Comment

by:objects
ID: 13714366
>> //pack(); If I add this line, the whole JPanel shrink to just hold the JPanel,
>> why is that?

from the javadoc:

"Causes this Window to be sized to fit the preferred size and layouts of its subcomponents. If the window and/or its owner are not yet displayable, both are made displayable before calculating the preferred size. The Window will be validated after the preferredSize is calculated."

0
 

Author Comment

by:yi02
ID: 13718644
Dear objects:

I did try what you suggested:

revalidate();
      repaint();

it works in that the whole JPanel doe not shrink, but I encounter another problem:

Since in my JPanel, there are other JLabels ( I dynamically add many JLabels to this JPanel and move them arround the JPanel), when I add a new JLabel and did the above codes you suggested, all the other JLabels move together at the top part of JPanel!"

So could you please tell me how to overcome this problem? Thanks a lot.

To accommadate all the efforts of your guys, I increased the points to 400.

thanks,

yi02
0
 
LVL 92

Expert Comment

by:objects
ID: 13721612
> I dynamically add many JLabels to this JPanel and move them arround the JPanel

as your using a layout manager you should not be moving components, that is the job of the layout manager.
If you want to explicitly position components you need to use no layout manager (set layoutmanager to null), and set the size and position of all components when you add them.

> all the other JLabels move together at the top part of JPanel

resizethe panel for example will cause the same to happen
0
 

Author Comment

by:yi02
ID: 13722065
Dear objects:

You are right. Even when I resize my panel, which caused the same to happen!

But I do need the capacity to move arround the JLabels within the JPanel!

When I set Layoutmanager to null using "this.setLayout(null);" in JPanel class, when I add JLabel, which now is invisible?!

Any solution that allows me move components but also use layout manager?

Thanks a lot!

yi02
0
 
LVL 92

Expert Comment

by:objects
ID: 13722123
> which now is invisible?!

as well as setting the position, you also need to set the size
0
 
LVL 37

Expert Comment

by:zzynx
ID: 13724394
>> Any solution that allows me move components but also use layout manager?
I'm afraid not.
Or you let the layout manager decide where to place the components (according to its layout)
Or you do it ALL yourself
0
 

Author Comment

by:yi02
ID: 13729688
Dear objects and zzynx:

>as well as setting the position, you also need to set the size
that is why I used the layoutmanager, since I need the manager to determine the size of the JLabel based on a given string. So I did not use the size. Do you have a better way that does not use Layoutmanager, but can let the JLabel to fit a given string based on the length of the string? Thanks a lot.

>> Any solution that allows me move components but also use layout manager?
>I'm afraid not.
Do you have a better way that does not use Layoutmanager, but can let the JLabel to fit a given string based on the length of the string? Thanks a lot.

I used to have to calculate the length of string and then determine the width of JLabel before adding it dynamically to the JPanel. Now I am trying to do it with LayoutManager but it appears failed.


y02



0
 
LVL 92

Accepted Solution

by:
objects earned 1200 total points
ID: 13730810
You can get the preferred size of the label using:

Dimension size = label.getPreferredSize();

Then use that to size your label.
0
 

Author Comment

by:yi02
ID: 13731368
Dear objects:

Your suggestion Dimension size = label.getPreferredSize(); kind of works for the purpose of fit the JLabel to any given string. Thanks a lot!!!

But I did run into a situation as followed:

Since I need turn off the LayoutManager to keep the arrangement of those dynamically added JLabels, I have to turn off the LayoutManager after add the first JLabel dynamically. if I turn off from the beginning from the JFrame, I even could not see my JPanel (only see JFrame, so when I add JLabel to JPanel dynamically, I could not see the added JLabel as well):
(below is the code for JFrame and JPanel)
My question is: Is the LayoutManager  required for JPanel show up on the JFrame? Any solution that not use LayoutManager but still show up the JPanel on top of JFrame?


Public myFrame extends JFrame{
//Constructor
  public myFrame() {  
             
      super("My Frame");  // Call the constructor from the superclass,  
      MyCanvas canvas = new MyCanvas();
       getContentPane().setLayout(new BorderLayout()); //if I eliminate these two lines,
       getContentPane().add(canvas, BorderLayout.CENTER); //I can not even see the JPanel

......
     setLocation(0,0);
     setSize(750,600);
      show();
     }
}

Public MyCanvas extends JPanel {
MyCanvas() {
          super();
         setBackground(Color.white);
         addMouseListener(this);
         addMouseMotionListener(this);
         ......
    }

 void AddJLabel() {
            //add JLabel to the JPanel      
      MyLabel myLB=new MyLabel();
      this.add(myJB);
     
   }
}

Public class MyLabel extends JLabel {

//Constructor accept a text string
 MyLabel(){
          super();
        setBorder(BorderFactory.createLineBorder(Color.black));
        setText("MyLongLongLongString");
        Dimension size = getPreferredSize();
        setBounds(1,1,(int)size.getWidth(),(int)size.getHeight());
        setForeground(Color.black);
        setOpaque(true); //important for setBackground to work  
        setBackground(Color.red);
        setHorizontalAlignment(CENTER);
            addMouseListener(this);
            addMouseMotionListener(this);       }
     ...
}



Notice the two lines of code in class MyFrame:
getContentPane().setLayout(new BorderLayout());
getContentPane().add(canvas, BorderLayout.CENTER);

if I eliminate these two lines, I can not even see the JPanel. Is the LayoutManager  required for JPanel show up on the JFrame? Any solution that not use LayoutManager but still show up the JPanel on top of JFrame?

Thanks again!

Best regards,


yi02





0
 
LVL 92

Assisted Solution

by:objects
objects earned 1200 total points
ID: 13731491
> Is the LayoutManager  required for JPanel show up on the JFrame?

No it is just responsible for sizing and position the components.

>     getContentPane().setLayout(new BorderLayout()); //if I eliminate these two lines,

You only need to remove the layout manager from the panel that you are adding your labels to, you can keep the layout manager for your frame

Public MyCanvas extends JPanel {
MyCanvas() {
         setLayout(null);
         setBackground(Color.white);
         addMouseListener(this);
         addMouseMotionListener(this);
         ......
    }

0
 

Author Comment

by:yi02
ID: 13736187
Dear objects:

Thanks a lot. It works. Your solution is the most effective!!!! Greatly appreciated!

Best wishes to you!

yi02
0
 
LVL 37

Expert Comment

by:zzynx
ID: 13736888
Thanks
0
 
LVL 92

Expert Comment

by:objects
ID: 13741032
no worries :)
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

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

How to install Selenium IDE and loops for quick automated testing. Get Selenium IDE from http://seleniumhq.org Go to that link and select download selenium in the right hand column That will then direct you to their download page. From that p…
In this post we will learn different types of Android Layout and some basics of an Android App.
This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.
This video teaches viewers about errors in exception handling.
Suggested Courses
Course of the Month8 days, 12 hours left to enroll

764 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