sonlexqt
sonlexqt

Reputation: 6469

How to add JPanels to JScrollPane?

I'm implementing a simple chat application, using Java. I want my chat application to have the "bubble" message style like modern message apps, so I've built 2 classes LeftArrowBubble and RightArrowBubble which extend JPanel to illustrate sender & receiver bubbles, like this:

enter image description here

This is the code for my LeftArrowBubble class (quite alike for RightArrowBubble):

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.geom.Area;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JPanel;
/**
 * @author harsh
 */
public class LeftArrowBubble extends JPanel {
   private static final long serialVersionUID = -5389178141802153305L;
   private int radius = 10;
   private int arrowSize = 12;
   private int strokeThickness = 3;
   private int padding = strokeThickness / 2;
   @Override
   protected void paintComponent(final Graphics g) {
      final Graphics2D g2d = (Graphics2D) g;
      g2d.setColor(new Color(0.5f, 0.8f, 1f));
      int x = padding + strokeThickness + arrowSize;
      int width = getWidth() - arrowSize - (strokeThickness * 2);
      int bottomLineY = getHeight() - strokeThickness;
      g2d.fillRect(x, padding, width, bottomLineY);
      g2d.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
      g2d.setStroke(new BasicStroke(strokeThickness));
      RoundRectangle2D.Double rect = new RoundRectangle2D.Double(x, padding, width, bottomLineY, radius, radius);
      Polygon arrow = new Polygon();
      arrow.addPoint(20, 8);
      arrow.addPoint(0, 10);
      arrow.addPoint(20, 12);
      Area area = new Area(rect);
      area.add(new Area(arrow));
      g2d.draw(area);
   }
}

Now I have a JFrame window with a JScrollPane on it, which looks like this:

enter image description here

What I want to do now is when I click on that CreateNewBubble button, a new Left(or Right)ArrowBubble JPanel will be created & displayed inside that JScrollPane (and this JScrollPane will be vertical scrollable if there're more bubbles inside of it). I've already tried this way:

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
    BubbleTest.LeftArrowBubble leftArrowBubble = new BubbleTest.LeftArrowBubble();
    jScrollPane1.add(leftArrowBubble);
}

But it didn't work as I expected: nothing shows up in the JScrollPane after clicking the button! I've been stuck at this problem for hours, really appreciate if you guys can help!

Upvotes: 0

Views: 1336

Answers (2)

Boann
Boann

Reputation: 50041

You can't use .add that way on a JScrollPane. A JScrollPane can only scroll a single component, which is set by either passing it to its constructor, or by calling .setViewportView.

Instead, create a separate container for the bubbles, such as a vertical Box, and set that as the single component scrolled by the scroll pane:

Box box = new Box(BoxLayout.Y_AXIS);
JScrollPane jScrollPane1 = new JScrollPane(box);

When you add a bubble, add it to the box (and call .revalidate() to lay it out):

box.add(leftArrowBubble);
box.revalidate();

Edit: Also, your bubbles will not, by default, have any size, unless you give them a size such as by calling setPreferredSize or by overriding getPreferredSize or by putting components inside them.

Upvotes: 3

sarcan
sarcan

Reputation: 3165

With JScrollPane you should always add components to the scroll pane's JViewPort. Look at the documentation here, it explains the concept behind the class rather well.

Short summary: A JScrollPane holds the scroll bars and a view port. The view port is a component that displays only a portion of its content - in this case the part that is visible on screen. The scroll bars tell the view port which portion to show.

Upvotes: 2

Related Questions