Search code examples
javaswingjpanelalignmentboxlayout

How to solve misalignment in boxlayout?


I'm trying to add multiple Jlabels in a Jpanel with Box layout, But i'm facing prolems on setting their setAlignmentX() . I'm reffering to an example from this site of Text bubble border and trying to pull out some examples from it. The jpanel is then added in Jscrollpane.

My code is here !!!

//Source :Andrew Thompson

 class TextBubbleBorder extends AbstractBorder {
 private Color color;
 private int thickness = 4;
 private int radii = 8;
private int pointerSize = 7;
private Insets insets = null;
private BasicStroke stroke = null;
private int strokePad;
private int pointerPad = 4;
private boolean left = true;
RenderingHints hints;

TextBubbleBorder(
        Color color) {
    new TextBubbleBorder(color, 4, 8, 7);
}

TextBubbleBorder(
        Color color, int thickness, int radii, int pointerSize) {
    this.thickness = thickness;
    this.radii = radii;
    this.pointerSize = pointerSize;
    this.color = color;

    stroke = new BasicStroke(thickness);
    strokePad = thickness / 2;

    hints = new RenderingHints(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);

    int pad = radii + strokePad;
    int bottomPad = pad + pointerSize + strokePad;
    insets = new Insets(pad, pad, bottomPad, pad);
}

TextBubbleBorder(
        Color color, int thickness, int radii, int pointerSize, boolean left) {
    this(color, thickness, radii, pointerSize);
    this.left = left;
}

@Override
public Insets getBorderInsets(Component c) {
    return insets;
}

@Override
public Insets getBorderInsets(Component c, Insets insets) {
    return getBorderInsets(c);
}

@Override
public void paintBorder(
        Component c,
        Graphics g,
        int x, int y,
        int width, int height) {

    Graphics2D g2 = (Graphics2D) g;

    int bottomLineY = height - thickness - pointerSize;

    RoundRectangle2D.Double bubble = new RoundRectangle2D.Double(
            0 + strokePad,
            0 + strokePad,
            width - thickness,
            bottomLineY,
            radii,
            radii);

    Polygon pointer = new Polygon();

    if (left) {
        // left point
        pointer.addPoint(
                strokePad + radii + pointerPad,
                bottomLineY);
        // right point
        pointer.addPoint(
                strokePad + radii + pointerPad + pointerSize,
                bottomLineY);
        // bottom point
        pointer.addPoint(
                strokePad + radii + pointerPad + (pointerSize / 2),
                height - strokePad);
    } else {
        // left point
        pointer.addPoint(
                width - (strokePad + radii + pointerPad),
                bottomLineY);
        // right point
        pointer.addPoint(
                width - (strokePad + radii + pointerPad + pointerSize),
                bottomLineY);
        // bottom point
        pointer.addPoint(
                width - (strokePad + radii + pointerPad + (pointerSize / 2)),
                height - strokePad);
    }

    Area area = new Area(bubble);
    area.add(new Area(pointer));

    g2.setRenderingHints(hints);

    // Paint the BG color of the parent, everywhere outside the clip
    // of the text bubble.
    Component parent  = c.getParent();
    if (parent!=null) {
        Color bg = parent.getBackground();
        Rectangle rect = new Rectangle(0,0,width, height);
        Area borderRegion = new Area(rect);
        borderRegion.subtract(area);
        g2.setClip(borderRegion);
        g2.setColor(bg);
        g2.fillRect(0, 0, width, height);
        g2.setClip(null);
    }

    g2.setColor(color);
    g2.setStroke(stroke);
    g2.draw(area);
}}

 //TextBubbleBorder ends here

Msgbox starts here

class msgbox extends JPanel {

    boolean ij = true;
    String msg = "";
    JLabel jl;

    msgbox() {
        //  msgpnl();
    }

    msgbox(String str, boolean bj) {
        ij = bj;
        msg = str;
        msgpnl();
    }
    /* public void setText(String str, boolean  bj){
     ij=bj;
     msg=str;
     msgpnl();
     }
     */

    public void msgpnl() {
        //setLayout(new GridLayout(0, 1));
        this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
        if (ij) {
            jl = new JLabel(msg);

            jl.setOpaque(true);
            jl.setBorder(new TextBubbleBorder(Color.LIGHT_GRAY, 1, 10, 7, ij));

            jl.setBackground(new Color(123, 104, 238));
            jl.setAlignmentX(0);
        } else {
            jl = new JLabel(msg, SwingConstants.RIGHT);

            jl.setOpaque(true);
            jl.setBorder(new TextBubbleBorder(Color.LIGHT_GRAY, 1, 10, 7, ij));

            jl.setBackground(new Color(224, 102, 255));
            jl.setAlignmentX(1);
        }
        this.add(jl);
        System.out.print("\nThis executed");
    }
}

chatpanel

class chatpanel extends JScrollPane {

    static JPanel jp;

    chatpanel() {
        this.setVisible(true);
        //this.setLayout(null);
        this.jp = new JPanel();
        this.jp.setLayout(new BoxLayout(this.jp, BoxLayout.Y_AXIS));
        //jp= new JPanel( new GridLayout(0, 1,0,5));
        //this.setLayout(new GridLayout(1,1));
        this.getViewport().add(jp);
        jp.setVisible(true);
        setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
        setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    }

    public void addmsg(Component co) {
        //msgscp.add(co);
        //co.setSize(100, 30);
        jp.add(co);
    }

    public static void main(String args[]) {
        JFrame jf = new JFrame("Testing msgpanel");
        jf.setLayout(new GridLayout(0, 1, 0, 0));
        chatpanel cp = new chatpanel();
        JButton jb = new JButton("new");
        msgbox mb;
        mb = new msgbox("<html><body style='width: 200px; padding: 5px;'>"
                + "<h1>Do U C Me?</h1>"
                + "Here is a long string that will wrap.  "
                + "The effect we want is a multi-line label.", true);
        // mb.setText();
        cp.addmsg(mb);
        msgbox mb2 = new msgbox("Hello 2", false);
        cp.addmsg(mb2);
        jb.setSize(100, 30);
        jf.add(cp);
        //jf.add(jb);
        jf.setSize(400, 400);
        //jf.pack();
        jf.setVisible(true);
    }
}

Plus i think i will face problem while wrapping up text in Jlabel, although i used HTML wrapping technique in chatpanel. that will not be effecient with changing sizes of msgboxes!! thanks in advance for help!!


Solution

  • enter image description hereenter image description here

    only in due all my respect to @Andrew Thompson :-) and my curiosity

    import java.awt.BorderLayout;
    import java.awt.Component;
    import java.awt.EventQueue;
    import java.awt.Rectangle;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.BoxLayout;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.ScrollPaneConstants;
    
    public class ChatPanel {
    
        private JFrame jf = new JFrame("Testing msgpanel");
        private JScrollPane scroll = new JScrollPane();
        private JPanel jp;
        private ChatPaneMsgBox mb;
        private ChatPaneMsgBox mb2;
        private JPanel cp = new JPanel();
        private JButton jb = new JButton("  ME !!! ");
        private JButton jb1 = new JButton("  YOU !!! ");
    
        public ChatPanel() {
            jp = new JPanel();
            jp.setLayout(new BoxLayout(jp, BoxLayout.Y_AXIS));
            mb = new ChatPaneMsgBox("<html><body style='width: 200px; padding: 5px;'>"
                    + "<h1>Do U C Me?</h1>"
                    + "Here is a long string that will wrap.  "
                    + "The effect we want is a multi-line label.", true);
            addmsg(mb);
            mb2 = new ChatPaneMsgBox("Hello 2", false);
            addmsg(mb2);
            scroll.setViewportView(jp);
            scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
            scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
            jb.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    mb = new ChatPaneMsgBox("<html><body style='width: 200px; padding: 5px;'>"
                            + "<h1>Do U C Me?</h1>"
                            + "Here is a long string that will wrap.  "
                            + "The effect we want is a multi-line label.", true);
                    addmsg(mb);
                    Rectangle rect = jp.getBounds();
                    Rectangle r2 = scroll.getViewport().getVisibleRect();
                    jp.scrollRectToVisible(new Rectangle((int) rect.getWidth(), 
                            (int) rect.getHeight(), (int) r2.getWidth(), (int) r2.getHeight()));
                }
            });
            jb1.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    mb2 = new ChatPaneMsgBox("Hello 2", false);
                    addmsg(mb2);
                    Rectangle rect = jp.getBounds();
                    Rectangle r2 = scroll.getViewport().getVisibleRect();
                    jp.scrollRectToVisible(new Rectangle((int) rect.getWidth(), 
                            (int) rect.getHeight(), (int) r2.getWidth(), (int) r2.getHeight()));
                }
            });
            cp.add(jb);
            cp.add(jb1);
            jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            jf.add(scroll);
            jf.add(cp, BorderLayout.SOUTH);
            jf.setSize(400, 400);
            jf.setVisible(true);
        }
    
        private void addmsg(Component co) {
            jp.add(co);
            jp.revalidate();
            jp.repaint();
        }
    
        public static void main(String args[]) {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new ChatPanel();
                }
            });
        }
    }
    

    .

    import java.awt.Color;
    import javax.swing.BoxLayout;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.SwingConstants;
    
    class ChatPaneMsgBox extends JPanel {
    
        boolean ij = true;
        private String msg = "";
        private JLabel jl;
    
        public ChatPaneMsgBox() {
        }
    
        public ChatPaneMsgBox(String str, boolean bj) {
            ij = bj;
            msg = str;
            msgpnl();
        }
    
        private void msgpnl() {
            this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
            if (ij) {
                jl = new JLabel(msg);
    
                jl.setOpaque(true);
                jl.setBorder(new TextBubbleBorder(Color.LIGHT_GRAY, 1, 10, 7, ij));
    
                jl.setBackground(new Color(123, 104, 238));
                jl.setAlignmentX(0);
            } else {
                jl = new JLabel(msg, SwingConstants.RIGHT);
    
                jl.setOpaque(true);
                jl.setBorder(new TextBubbleBorder(Color.LIGHT_GRAY, 1, 10, 7, ij));
    
                jl.setBackground(new Color(224, 102, 255));
                jl.setAlignmentX(1);
            }
            this.add(jl);
            System.out.print("\nThis executed");
        }
    }
    

    .

    import java.awt.BasicStroke;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Insets;
    import java.awt.Polygon;
    import java.awt.Rectangle;
    import java.awt.RenderingHints;
    import java.awt.geom.Area;
    import java.awt.geom.RoundRectangle2D;
    import javax.swing.border.AbstractBorder;
    
    class TextBubbleBorder extends AbstractBorder {
    
        private Color color;
        private int thickness = 4;
        private int radii = 8;
        private int pointerSize = 7;
        private Insets insets = null;
        private BasicStroke stroke = null;
        private int strokePad;
        private int pointerPad = 4;
        private boolean left = true;
        RenderingHints hints;
    
        TextBubbleBorder(Color color) {
            new TextBubbleBorder(color, 4, 8, 7);
        }
    
        TextBubbleBorder(Color color, int thickness, int radii, int pointerSize) {
            this.thickness = thickness;
            this.radii = radii;
            this.pointerSize = pointerSize;
            this.color = color;
            stroke = new BasicStroke(thickness);
            strokePad = thickness / 2;
            hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, 
                    RenderingHints.VALUE_ANTIALIAS_ON);
            int pad = radii + strokePad;
            int bottomPad = pad + pointerSize + strokePad;
            insets = new Insets(pad, pad, bottomPad, pad);
        }
    
        TextBubbleBorder(Color color, int thickness, int radii, int pointerSize, boolean left) {
            this(color, thickness, radii, pointerSize);
            this.left = left;
        }
    
        @Override
        public Insets getBorderInsets(Component c) {
            return insets;
        }
    
        @Override
        public Insets getBorderInsets(Component c, Insets insets) {
            return getBorderInsets(c);
        }
    
        @Override
        public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
            Graphics2D g2 = (Graphics2D) g;
            int bottomLineY = height - thickness - pointerSize;
            RoundRectangle2D.Double bubble = new RoundRectangle2D.Double(
                    0 + strokePad,
                    0 + strokePad,
                    width - thickness,
                    bottomLineY,
                    radii,
                    radii);
            Polygon pointer = new Polygon();
            if (left) {
                // left point
                pointer.addPoint(
                        strokePad + radii + pointerPad,
                        bottomLineY);
                // right point
                pointer.addPoint(
                        strokePad + radii + pointerPad + pointerSize,
                        bottomLineY);
                // bottom point
                pointer.addPoint(
                        strokePad + radii + pointerPad + (pointerSize / 2),
                        height - strokePad);
            } else {
                // left point
                pointer.addPoint(
                        width - (strokePad + radii + pointerPad),
                        bottomLineY);
                // right point
                pointer.addPoint(
                        width - (strokePad + radii + pointerPad + pointerSize),
                        bottomLineY);
                // bottom point
                pointer.addPoint(
                        width - (strokePad + radii + pointerPad + (pointerSize / 2)),
                        height - strokePad);
            }
            Area area = new Area(bubble);
            area.add(new Area(pointer));
            g2.setRenderingHints(hints);
            // Paint the BG color of the parent, everywhere outside the clip
            // of the text bubble.
            Component parent = c.getParent();
            if (parent != null) {
                Color bg = parent.getBackground();
                Rectangle rect = new Rectangle(0, 0, width, height);
                Area borderRegion = new Area(rect);
                borderRegion.subtract(area);
                g2.setClip(borderRegion);
                g2.setColor(bg);
                g2.fillRect(0, 0, width, height);
                g2.setClip(null);
            }
            g2.setColor(color);
            g2.setStroke(stroke);
            g2.draw(area);
        }
    }