How to get ellipsis in JLabel containing HTML?

When I combine HTML tags into JLabel text, I lose the ellipsis behavior that appears when the space is too small to display the full text. In my particular case, this is a TableCellRenderer that extends JLabel (default swing or other). Now that the column width is too small for the text to be shown fully, it does not show ellipses.

See the image below, for example: For the left column, I wrapped the text in the HTML renderer: setText("<html>" + "<strong>" + value.toString() + "</strong>" + "</html>"); . As you can see, when the column width is too small to contain text, it just gets cut. However, the right column showing the date and time and using DefaultTableCellRenderer shows the ellipsis when it does not contain the full text.

enter image description here

So my question is: can I have both? Sense, wrapping text with HTML and getting an ellipse?

UPDATE:

I found a reason not to get an ellipsis when using HTML. I followed the code from JComponent#paintComponent(Graphics g) up to BasicLabelUI#layoutCL(...) . See the following code snippet taken from the latter. This is only trimming the line if it does not have the html property (this is true when the label text is wrapped in html). But I have no idea how to get around this:

  v = (c != null) ? (View) c.getClientProperty("html") : null; if (v != null) { textR.width = Math.min(availTextWidth, (int) v.getPreferredSpan(View.X_AXIS)); textR.height = (int) v.getPreferredSpan(View.Y_AXIS); } else { textR.width = SwingUtilities2.stringWidth(c, fm, text); lsb = SwingUtilities2.getLeftSideBearing(c, fm, text); if (lsb < 0) { // If lsb is negative, add it to the width and later // adjust the x location. This gives more space than is // actually needed. // This is done like this for two reasons: // 1. If we set the width to the actual bounds all // callers would have to account for negative lsb // (pref size calculations ONLY look at width of // textR) // 2. You can do a drawString at the returned location // and the text won't be clipped. textR.width -= lsb; } if (textR.width > availTextWidth) { text = SwingUtilities2.clipString(c, fm, text, availTextWidth); textR.width = SwingUtilities2.stringWidth(c, fm, text); } textR.height = fm.getHeight(); } 
+7
source share
2 answers

I'm going to say: no, you cannot have both.

I think that if you need custom styles and ellipsis, you will have to do it yourself without HTML and using a custom TableCellRenderer.

If you want to try and eat your cake and eat it, you can get it by creating your own View object and setting it with c.putClientProperty ("html", value), but I suspect that the HTML rendering code has no concept of ellipses ( text overflow is a feature of HTML 5), so you will need to figure out how to teach it this. I suspect that it will be very difficult and much more complicated than just writing your own TableCellRenderer.

0
source

While the HTML content is simple, as in your question, ellipsis can be done using custom JLabel. Here is a working example. Just change the size of the window, and you will see that the ellipsis appears and disappears, and the text is cut accordingly when the size of the label changes with the window.

 import java.awt.Font; import java.awt.FontMetrics; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import javax.swing.JLabel; import javax.swing.border.Border; public class SimpleHTMLJLabel extends JLabel { private static final long serialVersionUID = -1799635451172963826L; private String textproper; private String ellipsis = "..."; private int textproperwidth; private FontMetrics fontMetrics; private int ellipsisWidth; private int insetsHorizontal; private int borderHorizontal; public SimpleHTMLJLabel(String textstart, String textproper, String textend) { super(textstart + textproper + textend); this.textproper = textproper; insetsHorizontal = getInsets().left + getInsets().right; fontMetrics = getFontMetrics(getFont()); calculateWidths(); addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent e) { int availablewidth = getWidth(); if (textproperwidth > availablewidth - (insetsHorizontal + borderHorizontal)) { String clippedtextproper = textproper; while (clippedtextproper.length() > 0 && fontMetrics.stringWidth(clippedtextproper) + ellipsisWidth > availablewidth - (insetsHorizontal + borderHorizontal)) { clippedtextproper = clipText(clippedtextproper); } setText(textstart + clippedtextproper + ellipsis + textend); } else { setText(textstart + textproper + textend); } } }); } private void calculateWidths() { if (textproper != null) { textproperwidth = fontMetrics.stringWidth(textproper); } if (ellipsis != null) { ellipsisWidth = fontMetrics.stringWidth(ellipsis); } } @Override public void setFont(Font font) { super.setFont(font); fontMetrics = getFontMetrics(getFont()); calculateWidths(); } private String clipText(String clippedtextproper) { return clippedtextproper.substring(0, clippedtextproper.length() - 1); } @Override public void setBorder(Border border) { super.setBorder(border); borderHorizontal = border.getBorderInsets(this).left + border.getBorderInsets(this).right; } } 

MAIN

 import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import javax.swing.BorderFactory; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; public class Main { public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { JFrame window = new JFrame(); window.setResizable(true); window.setTitle("Label Test"); window.getContentPane().add(getContent()); window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); window.setSize(400, 200); window.setLocationRelativeTo(null); window.setVisible(true); } }); } protected static Component getContent() { JPanel panel = new JPanel(new BorderLayout()); SimpleHTMLJLabel label = new SimpleHTMLJLabel("<html><strong>", "TEST1test2TEST3test4TEST5test6TEST7test8TEST", "<html><strong>"); label.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.BLUE, 5), BorderFactory.createEmptyBorder(10, 10, 10, 10))); label.setFont(label.getFont().deriveFont(20F)); panel.add(label, BorderLayout.CENTER); return panel; } } 
0
source

Source: https://habr.com/ru/post/990021/


All Articles