问题
I would like to understand why a JLabel, rendering HTML, shifts the vertical position of it's output text, whereas a JLabel which renders non-HTML, does not.
- Java version used: 1.6.0_37
- Swing Look and Feel used: Windows ("com.sun.java.swing.plaf.windows.WindowsLookAndFeel")
- OS: Windows 7 64 Bit
I did not put a SSCCE together since the code is really trivial. But if it helps please say so.
I rather give an examples using an images displaying the behavior:

I put a JPanel as the container around the JLabel to visualize the label's bounds. After setting the font and text for the JLabel, the
jLabel.getPreferredSize()
method returns the bounds of the rendered plain text or HTML (and this is the exact size I set for the surrounding JPanel). You can clearly see, that, if rendering HTML, the whole text is shifted a small amount down.
I would like to know why this happens and what I can do to correct the placement.
One workaround would be to translate the Graphics2D on which to render the text, to compensate the vertical shift, like this:
g2d.translate( 0, -20 );
But I don't know the correct y value in relation to the font metrics (e.g. font size). Anyway, this workaround also feels "wrong".
I really appreciate your answers, thanks a lot!
回答1:
It seems that if we set the Font
(family,size etc) for the HTML JLabel
using setFont(..)
the font is not rendered to the correct metrics of JLabel
.
Here is an example I made to demonstrate (Both JLabel
s shown are using HTML):

A simple work around is to the the font size, family etc in HTML too.
As we can see the cyan HTML JLabel
used setFont(..)
(and was incorrectly rendered) while the green HTML JLabel
used HTML to set the font and was rendered correctly:
JLabel labelHtml2 = new JLabel("<html><font size=10 family='Calibri'>" + text + "</font></html>");
Test.java:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static Font font = new Font("Calibri", Font.PLAIN, 38);
public Test() {
initComponents();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
new Test();
}
});
}
private void initComponents() {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String text = "Hello world";
//this label will not render correctly due to setting font via setFont(..)
JLabel labelHtml1 = new JLabel("<html>" + text + "</html>");
labelHtml1.setBackground(Color.CYAN);
labelHtml1.setOpaque(true);//so background will be painted
labelHtml1.setFont(font);
//this label will render correcty font is set via html
JLabel labelHtml2 = new JLabel("<html><font size=10 family='Calibri'>" + text + "</font></html>");
labelHtml2.setBackground(Color.GREEN);
labelHtml2.setOpaque(true);
//labelHtml2.setFont(font);
frame.add(labelHtml1, BorderLayout.NORTH);
frame.add(labelHtml2, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
}
来源:https://stackoverflow.com/questions/13219158/jlabel-shifts-the-text-vertically-down-while-displaying-html