Get height of multi line text with fixed width to make dialog resize properly

前端 未结 3 1560
别那么骄傲
别那么骄傲 2021-01-02 08:31

I want to create a dialog that contains some kind of text element (JLabel/JTextArea etc) that is multi lined and wrap the words. I want the dialog to be of a fixed width but

相关标签:
3条回答
  • 2021-01-02 09:15

    I found a solution to my problem. By replacing the JLabel with a JTextArea:

    JTextArea text = new JTextArea();
    text.setText(dummyString);
    text.setLineWrap(true);
    text.setWrapStyleWord(true);
    

    And calling pack() followed by an invocation to the layout manager to layout the components again followed by another pack:

    pack();
    layout.invalidateLayout(this.getContentPane());
    pack();
    

    This will cause the layout manager to adapt to the width.

    The complete code:

    import static javax.swing.GroupLayout.DEFAULT_SIZE;
    
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.*;
    
    public class TextSizeProblem3 extends JFrame {
      public TextSizeProblem3() {
    
        String dummyString = "";
        for (int i = 0; i < 100; i++) {
          dummyString += " word" + i;  //Create a long text
        }
        JTextArea text = new JTextArea();
        text.setText(dummyString);
        text.setLineWrap(true);
        text.setWrapStyleWord(true);
    
        JButton packMeButton = new JButton("pack");
        packMeButton.addActionListener(new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            pack();
          }
        });
    
        GroupLayout layout = new GroupLayout(this.getContentPane());
        getContentPane().setLayout(layout);
        layout.setVerticalGroup(layout.createParallelGroup()
            .addComponent(packMeButton)
            .addComponent(text)
        );
        layout.setHorizontalGroup(layout.createSequentialGroup()
            .addComponent(packMeButton)
            .addComponent(text, DEFAULT_SIZE, 400, 400) //Lock the width to 400
        );
    
        pack();
        layout.invalidateLayout(this.getContentPane());
        pack();
      }
    
      public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            JFrame frame = new TextSizeProblem3();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
          }
        });
      }
    }
    

    (you can add some customization (border, color etc) so it looks just like the JLabel but I have omitted that)

    0 讨论(0)
  • 2021-01-02 09:31

    Here is an adaptation of your code, doing what you want. But it needs a little trick to calculate the size of the label and set its preferred Size.

    I found the solution here

    import static javax.swing.GroupLayout.DEFAULT_SIZE;
    
    import java.awt.Dimension;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.*;
    import javax.swing.text.View;
    
    public class TextSizeProblem extends JFrame {
        public TextSizeProblem() {
    
            String dummyString = "";
            for (int i = 0; i < 100; i++) {
                dummyString += " word" + i; // Create a long text
            }
            JLabel text = new JLabel();
            text.setText("<html>" + dummyString + "</html>");
    
            Dimension prefSize = getPreferredSize(text.getText(), true, 400);
    
            JButton packMeButton = new JButton("pack");
            packMeButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    pack();
                }
            });
    
    
    
            GroupLayout layout = new GroupLayout(this.getContentPane());
            getContentPane().setLayout(layout);
            layout.setVerticalGroup(layout.createParallelGroup().addComponent(packMeButton)
                    .addComponent(text,DEFAULT_SIZE, prefSize.height, prefSize.height));
            layout.setHorizontalGroup(layout.createSequentialGroup().addComponent(packMeButton)
                    .addComponent(text, DEFAULT_SIZE, prefSize.width, prefSize.width) // Lock the width to 400
                    );
    
            pack();
        }
    
        public static void main(String args[]) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    JFrame frame = new TextSizeProblem();
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setVisible(true);
                }
            });
        }
    
        private static final JLabel resizer = new JLabel();
    
        /**
         * Returns the preferred size to set a component at in order to render an html string. You can
         * specify the size of one dimension.
         */
        public static java.awt.Dimension getPreferredSize(String html, boolean width, int prefSize) {
    
            resizer.setText(html);
    
            View view = (View) resizer.getClientProperty(javax.swing.plaf.basic.BasicHTML.propertyKey);
    
            view.setSize(width ? prefSize : 0, width ? 0 : prefSize);
    
            float w = view.getPreferredSpan(View.X_AXIS);
            float h = view.getPreferredSpan(View.Y_AXIS);
    
            return new java.awt.Dimension((int) Math.ceil(w), (int) Math.ceil(h));
        }
    }
    
    0 讨论(0)
  • 2021-01-02 09:34

    I think this is what you want:

    JLabel label = new JLabel("<html><div style=\"width:200px;\">Lots of text here...</div></html>");
    // add the label to some Container.
    

    This will restrict the JLabel to being 200 pixels wide and automatically adjust the height to fit the text.

    0 讨论(0)
提交回复
热议问题