2

我正在尝试在具有 Box 布局的 Jpanel 中添加多个 Jlabel,但我在设置它们的 setAlignmentX() 时遇到了问题。我正在参考此站点的文本气泡边框示例,并尝试从中提取一些示例。然后将 jpanel 添加到 Jscrollpane 中。

我的代码在这里!!!

//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

消息框从这里开始

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");
    }
}

聊天面板

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);
    }
}

另外,我认为在 Jlabel 中包装文本时会遇到问题,尽管我在聊天面板中使用了 HTML 包装技术。改变 msgboxes 的大小将不会有效!提前感谢您的帮助!!

4

3 回答 3

2

在此处输入图像描述在此处输入图像描述

只有在我对@Andrew Thompson 的所有尊重:-) 和我的好奇心

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);
    }
}
于 2013-07-19T08:35:42.027 回答
1

在这里给出的 msgbox 或 ChatPaneMsgBox 类中jl.setAlignmentX(0) 0 到 1 和 1 到 0的交换值。喜欢

      if (ij) {
              this.setLayout(new FlowLayout(FlowLayout.LEFT));
              //rest code
              jl.setAlignmentX(1); 
              //rest code here
              }
       else   {
               this.setLayout(new FlowLayout(FlowLayout.Right));
              //rest code
              jl.setAlignmentX(0); 
              //rest code here
              }

即使我现在认为 jl.setAlignmentX(); 不再重要了。

非常感谢 @mKorbel 和 @kleopatra 的帮助和建议。:-)

于 2013-07-19T08:28:58.393 回答
0

GridbagLayoutManager 在帮助保持矩形布局在宽度和自动调整大小方面易于管理方面做得很好。GridbagLayout 的编程机制是数据密集型的,这导致许多人逃避它。

早在 1996 年,我就在 Java.net 上的 Packer 项目下创建了 Packer 类。它将 GridbagLayoutManager 包装在一个子类中,该子类创建并使用 GridbagLayout 数据项来使事情正常工作。

要创建这样的简单布局,您只需要执行以下操作。

class MsgObject extends JPanel {
    public MsgObject(String text) {
        Packer pk = new Packer( this );
        pk.pack( new JLabel("<html><body>"+text+"</body></html>") ).fillBoth();
    }
}
class TheirMsgObject extends MsgObject {
    public TheirMsgObject( string text ) {
        super(text);
        setBackground( new Color( 255, 220, 230 ) );
    }
}
class MyMsgObject extends MsgObject {
    public MyMsgObject( string text ) {
        super(text);
        setBackground( new Color( 220, 230, 255 ) );
    }
}
class MsgPane extends JPanel {
    int items = -1;
    Packer mpk;
    BlankSpace = blank;
    class BlankSpace extends JPanel {
        public Dimension PreferredSize() {
            return new Dimension( 100, 2 );
        }
    }
    public void MsgPane() {
        mpk = new Packer( this);
        blank = new BlankSpace();
    }

    private void addMessage( MsgObject msg, int col ) {
        mpk.pack( msg ).gridx(0).gridy(++items).gridw(col).fillx(1);
    }
    public void addMessage( TheirMsgObject msg ) {
        addMessage( msg, 0 );
    }

    public void addMessage( MyMsgObject msg ) {
        addMessage( msg, 1 );
        mpk.pack( blank ).gridx(0).gridy(items);
    }
}

然后,您可以创建适当的 MsgObject 并将其添加到容器中,它就会出现在那里。您可以添加适当的代码以滚动添加等。

于 2014-02-24T17:39:31.940 回答