0

Part of the application I am building demands that I display a variable amount of text in a non-editable component of some sort. Currently this has been implemented in JTextArea, but JTextArea has only the setRows() to set the vertical size of the component.

What I want is a component that will expand to the size needed. This does not pose a problem since the panel on which this thing is embedded is scrollable. It doesn't have to all show up at any particular time but it has to be visible. (And I don't want scrollbars within scrollbars, which I consider an abomination.

What Swing component is best for these requirements?

(Note: I am only asking this here because the entire #$%^&* Oracle Java documentation site including all the Swing demos and tutorials appears to be down now).

Steve Cohen
  • 4,219
  • 7
  • 45
  • 84

2 Answers2

0

Emm... In the case you don't want to enter text you don't need JTextArea... Just to display some text you can simply use JLabel; JLabel supports html text format so you can easily use it in some way like this

...

JPanel aPanel=new JLanel(new FlowLayout());
JLabel aLabel=new JLabel();
aPanel.add(aLabel);


void showFormattedText(String html)
{
 aLabel.setText(html);
}

...

As you may guessed, the formatted text can be anything like this

<html>
Put some text<br>
...<br>

</html>

I hope you got the conception

...

mini parser - not tested

  String getFormattedText(String text)
{
  char commonBR='\n';
  String htmlBR="<br>";
  char check;
  String result="";

  for(int i=0; i<text.length(); i++)
  {
      check=text.charAt(i);
      if(check==commonBR)

    {

    result+=htmlBR;
    continue;
    }

    result+=check;

     }

     return result;

    }

...

void test
{
       String text="Hello world \n Hello World once again \n ...and again ";

       System.out.println(this.getFormattedText(text));
}

... it is not a final solution though but a basis conception. I hope it was helpful

Good luck

user592704
  • 3,564
  • 11
  • 64
  • 106
  • Thanks. I have inherited this code and that is what they used. However, I agree with you that JTextArea is not necessary since there is no editing. Just so I understand you though, since this is html if I don't put
    tags in will the JLabel be smart enough to break up the lines on its own and add rows as necessary (as an html page would)? The text I am displaying is just a random String of characters that were entered somewhere else. And will it be smart enough to break up on word boundaries? If so, then this is just what I need.
    – Steve Cohen Mar 23 '12 at 20:44
  • `Put some text
    ` Use styles rather than hard line breaks. That way the text can wrap to next line as needed, without any complications. See [an example](http://stackoverflow.com/a/7861833/418556).
    – Andrew Thompson Mar 23 '12 at 20:53
  • @SteveCohen No, the HTML content will not wrap automatically. See my example using CSS to fix that. – Andrew Thompson Mar 23 '12 at 20:54
  • if it is a web based app it is useful to transfer data in html format for it; Though you was saying as "What I want is a component that will expand to the size needed. " So the size max is supposed to be its content line length limit right? As if you are going to show a message as it used to be written with all its formatting? So you need to catch all previously entered formatting... Sure you can make your text being dependent of JLabel width (add CSS for it) but if you want JLabel being dependent of text lines length instead you can create something like a mini parser for your app ... – user592704 Mar 24 '12 at 01:22
  • ... as an example you can catch each \n character and replace it with
    . It is a very simple code; I just start its basis... watch my answer edited
    – user592704 Mar 24 '12 at 01:25
0

I've managed a working prototype for this addressing the dynamic resize issues in the original problem. As more text is added, the text area is resized to be big enough to contain the text. Obviously use setEditable(false) to stop editing of text. Hopefully it will give you some ideas.

  • set the text
  • change the column count to an approximate value - here I used square root of total characters * a arbitrary factor.
  • not the text area is a reasonable width, but we still need to fix the height.
  • set preferred size to a low value - this will force a recalculation
  • set preferred height to the minimum height - this is calculated from minimum bounding box of content.

Code

JFrame frame = new JFrame();
GroupLayout gLayout = new GroupLayout(frame.getContentPane());
frame.getContentPane().setLayout(gLayout);

final JTextArea area = new JTextArea();
area.setEditable(false);
area.setLineWrap(true);
area.setWrapStyleWord(true);

JButton button = new JButton("Add more");
button.addActionListener(new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent e) {
        area.setText(area.getText()
                + "apple banana carrot dingo eagle fox gibbon ");

        // set approx number of cols
        int chars = area.getText().length();
        int cols = (int) Math.round(Math.sqrt(chars) * 1.3);
        area.setColumns(cols);

        // force recalculation
        area.setPreferredSize(new Dimension(25, 25));

        // downsize
        area.setPreferredSize(new Dimension(
                area.getPreferredSize().width,
                area.getMinimumSize().height));

    }
});

ParallelGroup hGroup = gLayout
        .createParallelGroup()
        .addComponent(button)
        .addComponent(area, GroupLayout.PREFERRED_SIZE,
                GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE);
gLayout.setHorizontalGroup(hGroup);

SequentialGroup vGroup = gLayout
        .createSequentialGroup()
        .addComponent(button)
        .addComponent(area, GroupLayout.PREFERRED_SIZE,
                GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE);
gLayout.setVerticalGroup(vGroup);

frame.setSize(600, 500);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

frame.invalidate();
frame.validate();
frame.setVisible(true);
Adam
  • 32,907
  • 8
  • 89
  • 126