🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.jbuilder.java.swing
3 messages
3 total messages Started by Hal Brooks Sat, 20 Mar 2004 04:02
Layout Question - BoxLayout and JTextAreas. Example program included.
#1165
Author: Hal Brooks
Date: Sat, 20 Mar 2004 04:02
153 lines
5881 bytes
Hi all,

I'm trying to create a resizeable chat-ish area for displaying
messages.  Each message gets it own font.  Messages are stacked
vertically with the newest at the bottom, and a scrollbar allows
history access to older messages.  You get the idea.

What I've tried thus far is to use a JTextArea for each message (which
handles the necessary wordwrap), place all these onto a Box for
layout, use a JScrollPane for scrolling, and put the JScrollPane into
a JFrame for resizeability.  I had to derive from most of those to get
things even close to right.  

Problem is, the JTextArea-derived class is always a step behind in
calculating its preferred size.  So if you expand the frame
horizonally far enough that none of the lines need to wrap, then smash
it back to its minimum width, the text areas don't grow vertically to
account for the line wrap, and things look bad.

I've spent many hours on this, Googled various resources, read Help
files, references, and all sorts of things on Sun's site.  No luck.  I
would greatly appreciate any advice.  I'm still developing an
understanding of how Swing layout works.  For all I know, I'm
approaching this completely wrong.  I once did a similar thing in
Windows/C++ by implementing everything myself including the wordwrap
logic and all the drawing.  I was hoping to get Swing to do much of
the work for me.  The C++ solution took a while to code...

An example program follows.  I abused some good practices herein for
brevity.  (Ex.  public variables.)  I also put a red border around the
Box and a black border around each text area, and did some logging to
the console, to be able to tell what is going on.

----------------------------------------

import java.util.logging.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;


public class uitest {
  public static void main(String[] strings) {
    JFrame frame = new JFrame("UI Text");

    uiPanel uip = new uiPanel();
    frame.getContentPane().add(uip);
    frame.pack();
    frame.setVisible(true);

    uip.AUiBox.addUiText("Test Message One, \"serif\" font, plain, 12
point", new Font("serif", Font.PLAIN, 12));
    uip.AUiBox.addUiText("Text Message Two, \"monospaced\" font, bold,
14 point", new Font("monospaced", Font.BOLD, 14));
    uip.AUiBox.addUiText("Text Message Three, \"sansserif\" font,
italic, 18 point", new Font("monospaced", Font.ITALIC, 16));
  }
}


class uiPanel extends JPanel {
  public  final uiBox       AUiBox;

  public uiPanel() {
    setPreferredSize(new Dimension(350, 100));
    setLayout(new BorderLayout());

    AUiBox = new uiBox();
    final JScrollPane sp = new JScrollPane(AUiBox,

JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,

JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    sp.addComponentListener(new java.awt.event.ComponentAdapter() {
      public void componentResized(ComponentEvent e) {
        AUiBox.scrollPaneResized(sp.getViewport().getWidth());
      }
    });
    add(sp, BorderLayout.CENTER);
  }
}


class uiBox extends Box {
  public uiBox() {
    super(BoxLayout.Y_AXIS);
    setBorder(BorderFactory.createLineBorder(new Color(0xFF0000), 1));
  }

  public void addUiText(String text, Font font) {
    uiText uit = new uiText(text, font);
    add(uit);

    Dimension d = getSize();
    d.height += uit.recalcSize(d.width);
    setPreferredSize(d);
    setSize(d);
  }

  public void scrollPaneResized(int viewportWidth) {
    int newWidth = viewportWidth;
    int newHeight = 0;
    int numComponents = getComponentCount();
    for (int i = 0; i < numComponents; i++) {
      uiText uit = (uiText)getComponent(i);
      newHeight += uit.recalcSize(newWidth);
    }

    Dimension d = new Dimension(newWidth, newHeight);
    setMaximumSize(d);
    setMinimumSize(d);
    setPreferredSize(d);
    setSize(d);

    String msg = "newWidth:  " + newWidth + ", newHeight:  " +
newHeight;
    new ConsoleHandler().publish(new LogRecord(Level.SEVERE, msg));
  }
}


class uiText extends JTextArea {
  public uiText(String text, Font font) {
    super(text);
    setOpaque(false);
    setEditable(false);
    setLineWrap(true);
    setWrapStyleWord(true);
    setAlignmentX(0);
    setFont(font);

    setBorder(BorderFactory.createLineBorder(new Color(0), 1));
  }

  public int recalcSize(int parentWidth) {
    setMinimumSize(new Dimension(parentWidth, 0));
    setMaximumSize(new Dimension(parentWidth, Integer.MAX_VALUE));

    setSize(parentWidth, 1);

    String msg = "parentWidth:  " + parentWidth +
                 ", prefWidth:  " + getPreferredSize().getWidth() +
                 ", prefHeight:  " + getPreferredSize().getHeight();
    new ConsoleHandler().publish(new LogRecord(Level.SEVERE, msg));

    return (int)getPreferredSize().getHeight();
  }

  public Dimension getMaximumSize() {
    return new Dimension((int)super.getMaximumSize().getWidth(),
                         (int)getPreferredSize().getHeight());
  }
}
Re: Layout Question - BoxLayout and JTextAreas. Example program included.
#1176
Author: Greg Hamer
Date: Mon, 22 Mar 2004 18:02
159 lines
6460 bytes
You could use a JTextPane instead. It can handle multiple fonts in the
document.

"Hal Brooks" <dont@spamme.com> wrote in message
news:405bbe99.82703921@newsgroups.borland.com...
> Hi all,
>
> I'm trying to create a resizeable chat-ish area for displaying
> messages.  Each message gets it own font.  Messages are stacked
> vertically with the newest at the bottom, and a scrollbar allows
> history access to older messages.  You get the idea.
>
> What I've tried thus far is to use a JTextArea for each message (which
> handles the necessary wordwrap), place all these onto a Box for
> layout, use a JScrollPane for scrolling, and put the JScrollPane into
> a JFrame for resizeability.  I had to derive from most of those to get
> things even close to right.
>
> Problem is, the JTextArea-derived class is always a step behind in
> calculating its preferred size.  So if you expand the frame
> horizonally far enough that none of the lines need to wrap, then smash
> it back to its minimum width, the text areas don't grow vertically to
> account for the line wrap, and things look bad.
>
> I've spent many hours on this, Googled various resources, read Help
> files, references, and all sorts of things on Sun's site.  No luck.  I
> would greatly appreciate any advice.  I'm still developing an
> understanding of how Swing layout works.  For all I know, I'm
> approaching this completely wrong.  I once did a similar thing in
> Windows/C++ by implementing everything myself including the wordwrap
> logic and all the drawing.  I was hoping to get Swing to do much of
> the work for me.  The C++ solution took a while to code...
>
> An example program follows.  I abused some good practices herein for
> brevity.  (Ex.  public variables.)  I also put a red border around the
> Box and a black border around each text area, and did some logging to
> the console, to be able to tell what is going on.
>
> ----------------------------------------
>
> import java.util.logging.*;
> import javax.swing.*;
> import java.awt.*;
> import java.awt.event.*;
>
>
> public class uitest {
>   public static void main(String[] strings) {
>     JFrame frame = new JFrame("UI Text");
>
>     uiPanel uip = new uiPanel();
>     frame.getContentPane().add(uip);
>     frame.pack();
>     frame.setVisible(true);
>
>     uip.AUiBox.addUiText("Test Message One, \"serif\" font, plain, 12
> point", new Font("serif", Font.PLAIN, 12));
>     uip.AUiBox.addUiText("Text Message Two, \"monospaced\" font, bold,
> 14 point", new Font("monospaced", Font.BOLD, 14));
>     uip.AUiBox.addUiText("Text Message Three, \"sansserif\" font,
> italic, 18 point", new Font("monospaced", Font.ITALIC, 16));
>   }
> }
>
>
> class uiPanel extends JPanel {
>   public  final uiBox       AUiBox;
>
>   public uiPanel() {
>     setPreferredSize(new Dimension(350, 100));
>     setLayout(new BorderLayout());
>
>     AUiBox = new uiBox();
>     final JScrollPane sp = new JScrollPane(AUiBox,
>
> JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
>
> JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
>     sp.addComponentListener(new java.awt.event.ComponentAdapter() {
>       public void componentResized(ComponentEvent e) {
>         AUiBox.scrollPaneResized(sp.getViewport().getWidth());
>       }
>     });
>     add(sp, BorderLayout.CENTER);
>   }
> }
>
>
> class uiBox extends Box {
>   public uiBox() {
>     super(BoxLayout.Y_AXIS);
>     setBorder(BorderFactory.createLineBorder(new Color(0xFF0000), 1));
>   }
>
>   public void addUiText(String text, Font font) {
>     uiText uit = new uiText(text, font);
>     add(uit);
>
>     Dimension d = getSize();
>     d.height += uit.recalcSize(d.width);
>     setPreferredSize(d);
>     setSize(d);
>   }
>
>   public void scrollPaneResized(int viewportWidth) {
>     int newWidth = viewportWidth;
>     int newHeight = 0;
>     int numComponents = getComponentCount();
>     for (int i = 0; i < numComponents; i++) {
>       uiText uit = (uiText)getComponent(i);
>       newHeight += uit.recalcSize(newWidth);
>     }
>
>     Dimension d = new Dimension(newWidth, newHeight);
>     setMaximumSize(d);
>     setMinimumSize(d);
>     setPreferredSize(d);
>     setSize(d);
>
>     String msg = "newWidth:  " + newWidth + ", newHeight:  " +
> newHeight;
>     new ConsoleHandler().publish(new LogRecord(Level.SEVERE, msg));
>   }
> }
>
>
> class uiText extends JTextArea {
>   public uiText(String text, Font font) {
>     super(text);
>     setOpaque(false);
>     setEditable(false);
>     setLineWrap(true);
>     setWrapStyleWord(true);
>     setAlignmentX(0);
>     setFont(font);
>
>     setBorder(BorderFactory.createLineBorder(new Color(0), 1));
>   }
>
>   public int recalcSize(int parentWidth) {
>     setMinimumSize(new Dimension(parentWidth, 0));
>     setMaximumSize(new Dimension(parentWidth, Integer.MAX_VALUE));
>
>     setSize(parentWidth, 1);
>
>     String msg = "parentWidth:  " + parentWidth +
>                  ", prefWidth:  " + getPreferredSize().getWidth() +
>                  ", prefHeight:  " + getPreferredSize().getHeight();
>     new ConsoleHandler().publish(new LogRecord(Level.SEVERE, msg));
>
>     return (int)getPreferredSize().getHeight();
>   }
>
>   public Dimension getMaximumSize() {
>     return new Dimension((int)super.getMaximumSize().getWidth(),
>                          (int)getPreferredSize().getHeight());
>   }
> }
>
Re: Layout Question - BoxLayout and JTextAreas. Example program included.
#1090
Author: Hal Brooks
Date: Wed, 24 Mar 2004 06:21
16 lines
1645 bytes
On Mon, 22 Mar 2004 10:02:17 -0800, "Greg Hamer"
<ghamer@dslextreme.com> wrote:

>You could use a JTextPane instead. It can handle multiple fonts in the
>document.

Thanks Greg!  I'd looked at this control before, but has misunderstood
some things about it.  I've taken a second look and it seems
promising.

However, I'm struggling to understand all its capabilities.  I've
looked through the Help documentation, and the Sun tutorial that the
Help links to, as well as two Java books (Eckel's and Horstmann's).
But I still haven't found anything that really describes how to to
take advantage of the power that JTextPane seems to have.  Any
suggestions about good places to find examples and/or tutorials?
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads