2

In Java 8, if I set a JTextPane's width to match the value returned by FontMetrics.stringWidth, the text fits exactly and is drawn on one line. But, in Java 17, with the same code, the last word in the text is wrapped. Here's my code:

import java.awt.*;
import javax.swing.*;

public class SimpleTest {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(SimpleTest::test);
    }

    private static void test() {
        Test test = new Test();
        JPanel panel = new JPanel(new BorderLayout());
        panel.add(test);
        JFrame frame = new JFrame();
        frame.setContentPane(panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(250, 100);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private static class Test extends JComponent {

        private static final long serialVersionUID = 1L;
        private JTextPane textPane;

        private Test() {
            textPane = new JTextPane();
            textPane.setFont(new Font("Arial", Font.BOLD, 24));
            textPane.setBorder(null);
            textPane.setContentType("text/plain");
        }

        @Override
        protected void paintComponent(Graphics g) {
            String labelText = "THIS IS A TEST";
            textPane.setText(labelText);
            textPane.setLocation(new Point(0, 0));
            FontMetrics fm = textPane.getFontMetrics(textPane.getFont());
            int width = fm.stringWidth(labelText);
            int height = fm.getHeight();
            textPane.setSize(width, height);
            Graphics2D g2D = (Graphics2D) g.create(0, 0, width, height * 2);
            textPane.paint(g2D);
            g2D.dispose();
        }

    }

}

Java 8: Java 8 Java 17: Java 17

Is it possible to make the behavior consistent?

David Struck
  • 157
  • 1
  • 9
  • 5
    This is a common [pitfall](https://stackoverflow.com/a/12532237/230513); let the layout solve it for you. – trashgod Aug 20 '21 at 18:54
  • 5
    A painting method is for painting only. The painting method should NOT change properties of the component. So it should NOT be setting the text or the size of the component. There is no need to override the paintComponent() method. The preferred size method of the text pane will calculate the correct size. You should NOT use frame.setSize(). Instead you use `frame.pack()` and all components will be display at their preferred size. – camickr Aug 20 '21 at 19:26
  • Thanks, all! I agree with all the sentiments expressed here. Note that what our software does is use a JTextPane to draw styled text to a layered pane, hence why we are overriding paintComponent. If that weren't the case then, yes, I would let the layout size things for me and I would call frame.pack() rather than setting the frame's size. In any case, you put me on the right track -- rather than using FontMetrics to calculate the width, I can get the text pane's preferred width after setting its text. This gives me the width I'm looking for in both Java 8 and Java 17. – David Struck Sep 10 '21 at 19:29

2 Answers2

0

To get the width, call this:

int width = textPane.getPreferredSize().width;

Not this:

int width = fm.stringWidth(labelText);
David Struck
  • 157
  • 1
  • 9
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-ask). – Community Sep 10 '21 at 20:13
-1

I don't know the specifics of it, but I'm 100% sure that in Java 8 the method fm.stringWidth(labelText) is 1 greater than it is in Java 11 because if I do fm.stringWidth(labelText)+1 then the line wrapping works. Just change that line, and your code will work.

Please let me know if this helps.

Dequog
  • 124
  • 13
  • I would've put it in a comment, but look at my rep, I don't have that privilege, and the downvote doesn't help – Dequog Aug 21 '21 at 01:56
  • 1
    *"I don't have that privilege"* Oh, my bad. But there is a reason for that. Well demonstrated by this answer. *"the downvote doesn't help"* Sure it does, if it encourages people not to post complete nonsense. You should have read my comment all the way to the end, as it contains 'meta' information relevant to the answer i.e. it is noise that would be better never having been posted in any form. – Andrew Thompson Aug 21 '21 at 02:12