简体   繁体   中英

JLabel unexpected Text-Alignment behaviour when Icon is Null

How do I get around the apparent limitation of JLabel ignoring placement directives if the icon is null ?

I have an app that uses a JLabel to show an Icon with explanatory text but sometimes the JLabel contains text-only and no corresponding Icon.

I have the alignment on the JLabel set as follows :

label5.setHorizontalAlignment(JLabel.CENTER);
label5.setVerticalAlignment(JLabel.TOP);
label5.setHorizontalTextPosition(JLabel.CENTER);
label5.setVerticalTextPosition(JLabel.BOTTOM);
label5.setIconTextGap(-3);

This all works perfectly when there is an Icon present. Icon above, text below.

However, if the Icon is null (because the icon source file (gif/jpg etc) is missing from the nominated location or because the icon is set deliberately to null) then the text does NOT show at the bottom, but rather resets to the TOP of the Label.

I thought it might be something peculiar to do with my negative IconTextGap but I have been able to demonstrate the same behaviour on a standard Java JLabel example program (from www.java2s.com/Code/Java/Swing-JFC/LabelTextPosition.htm )

import java.awt.Container;
import java.awt.GridLayout;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;

public class LabelTextPos {

  public static void main(String args[]) {
    JFrame frame = new JFrame("Label Text Pos");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    Container content = frame.getContentPane();
    content.setLayout(new GridLayout(2, 2));

    Border border = LineBorder.createGrayLineBorder();
    Icon warnIcon = new ImageIcon("Warning.gif");

    JLabel label1 = new JLabel(warnIcon);
    label1.setText("Left-Bottom");
    label1.setHorizontalTextPosition(JLabel.LEFT);
    label1.setVerticalTextPosition(JLabel.BOTTOM);
    label1.setBorder(border);
    content.add(label1);

    JLabel label2 = new JLabel(warnIcon);
    label2.setText("Right-TOP");
    label2.setHorizontalTextPosition(JLabel.RIGHT);
    label2.setVerticalTextPosition(JLabel.TOP);
    label2.setBorder(border);
    content.add(label2);

    JLabel label3 = new JLabel(warnIcon);
    label3.setText("Center-Center");
    label3.setHorizontalTextPosition(JLabel.CENTER);
    label3.setVerticalTextPosition(JLabel.CENTER);
    label3.setBorder(border);
    content.add(label3);

    JLabel label4 = new JLabel(warnIcon);
    label4.setText("Center-Bottom");
    label4.setHorizontalTextPosition(JLabel.CENTER);
    label4.setVerticalTextPosition(JLabel.BOTTOM);
    label4.setBorder(border);
    content.add(label4);

    frame.setSize(300, 200);
    frame.setVisible(true);
  }
}

When the ICON source file is present, you get the desired result :

JLabel显示预期的行为

But if the ICONS are Null, the JLabel pays no attention to the Text Placement parameters :

JLable显示意外行为

I see that the JLabel Documentation says of setVerticalTextAlignment :

Sets the vertical position of the label's text, relative to its image .

But as you can see from the screensnaps above, where the Icon is actually null, it seems to bypass the JLabel location calculation code altogether.

I searched a lot before posting this but couldn't find anywhere that this specific issue is discussed.

So, is there a known or easy solution to this problem ? I am fairly sure that I could create a new JLabel when I want to display the Text only, instead of setting the icon on the existing JLabel to Null, and the new JLabel without ever having had an icon would probably show the text in the desired location, but I would prefer not to go creating new Objects when the old ones are essentially doing what I need 95% of the time.

I could also create a see-through icon of the appropriate size to keep my text at the bottom, but again that seems like a bit of a hack. Suggestions ?

Yes,

JLabel s text position is relative to the icon. So, if it's icon is null definitely it will be aligned to the center. If you want to get rid of the problem, you will have to set an empty icon to the JLabel with required size.

You can use following methods to create an empty Icon and set Icon to the JLabel

//use this method to set icon to the label
private void setIcon(JLabel label, Icon icon) {
    if (icon == null) {
        icon = getEmptyIcon();
    }

    label.setIcon(icon);
}

//crete an empty icon
private Icon getEmptyIcon() {
    BufferedImage bufferedImage = new BufferedImage(24, 24, BufferedImage.TYPE_INT_ARGB);
    return new ImageIcon(bufferedImage);
}

How do I get around the apparent limitation of JLabel ignoring placement directives if the icon is null ?

You have set the properties to control how the text/icon are relative to one another.

However, you haven't set the properties to control how the text/icon are relative to the total space of the JLabel itself.

You need to set the horizontal/vertical alignment of the text.

The default values are CENTER , which means the text/icon are centered within the space of the label.

For example:

label1.setVerticalAlignment(JLabel.BOTTOM);
label1.setHorizontalAlignment(JLabel.LEFT);

Try resizing the frame and see how both the text/icon remain displayed at the bottom/left.

So you have two alignments to consider:

  1. text/icon relative to the size of the JLabel
  2. text/icon relative to each other.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM