Ryan Ryan - 1 month ago 9
HTML Question

How to stop a JButton's height from changing after adding an underline?

So I have a

JButton
that when you move your mouse over it, an underline appears using HTML. However when the underline is added it makes the
JButton
a tad bit larger than it's supposed to be.

I have tried a few things like

button.setMaximumSize(button.getPreferredSize());


before the underline is added, but I haven't been able to fix it. So how do I make sure the height stays the same, regardless if the underline is present or not.

I have a sample class below that demonstrates the problem (I couldn't get it to have the exact same severity, but it's enough to show the problem).

SAMPLE CLASS

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.plaf.metal.MetalButtonUI;

public class UnderlineSample extends JFrame {
public UnderlineSample() {
super("Underline Sample");
setLayout(new GridBagLayout());
setDefaultCloseOperation(EXIT_ON_CLOSE);
setPreferredSize(new Dimension(300, 150));

String text =
"<html>"
+ "<p style = 'border-bottom: 1px solid rgba(0,0,0,0,0); box-sizing: border-box;'>"
+ "<span style = 'color: rgb(0, 0, 255); font-weight: bold;'>"
+ "Sample"
+ "</span> "
+ " underline button"
+ "</p>"
+ "</html>";
JButton button = new JButton(text);
button.setFont(new Font("", Font.PLAIN, 18));
button.setFocusable(false);
button.setBackground(Color.LIGHT_GRAY);
button.setForeground(Color.BLACK);
button.setUI(new MetalButtonUI());
button.setHorizontalAlignment(SwingConstants.LEFT);
button.setAlignmentX(LEFT_ALIGNMENT);

button.addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent e) {
String s =
"<html>"
+ "<p style = 'border-bottom: 1px solid black; box-sizing: border-box;'>"
+ "<span style = 'color: rgb(0, 0, 255); font-weight: bold;'>"
+ "Sample"
+ "</span> "
+ " underline button"
+ "</p>"
+ "</html>";
button.setText(s);
}

public void mouseExited(MouseEvent e) {
String s =
"<html>"
+ "<p style = 'border-bottom: 1px solid rgba(0,0,0,0,0); box-sizing: border-box;'>"
+ "<span style = 'color: rgb(0, 0, 255); font-weight: bold;'>"
+ "Sample"
+ "</span> "
+ " underline button"
+ "</p>"
+ "</html>";
button.setText(s);
}
});

GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0; gbc.gridy = 0; gbc.anchor = GridBagConstraints.WEST;
gbc.weightx = 1; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.ipady = 10;
gbc.insets = new Insets(0, 10, 5, 10);

add(button, gbc);

pack();
setVisible(true);
}

public static void main(String[] args) {
new UnderlineSample();
}
}

Answer

Rendering of html/css in Swing does not have support for all css styles. Case in point rgba does not work (you can test this yourself by adding a colored border using rgba that you expect to be rendered rather than one with alpha 0 and see the result).

In other words, the border with rgba is not being rendered, hence the change in size when you add a renderable border-bottom with the MouseListener.mouseEntered. You can trick it by using rgb that has the same color as the background color. Something like:

<p style = 'border-bottom: 1px solid rgb(200,200,200); box-sizing: border-box;'>