java - 如何在 JTextPane 中嵌入可调整大小的 JPanel?

标签 java image swing jpanel jtextpane

相反,将 JTextPane 插入到 JPanel 中会有很多问题。这不是我的问题。我需要能够将自定义 JPanel(带有拖放、拖动和鼠标单击监听器)插入到 JTextPane 中,然后将其放入 JScrollPane 中,最后放入 JFrame 中进行显示。原因是因为我需要一个支持通过在聊天客户端中拖动来调整大小的图像,该图像本身主要是文本。

足够方便的是,JTextPane 中有一个相关的方法:insertComponent(Component c),但是每当我使用它时,我的组件最终都会被压缩到恰好一行文本的空间(即使它们报告具有更大的尺寸) )。这对于普通按钮来说是完美的,但如果我需要更大的按钮,我就不走运了。我可以使用 ImageIcons 自行插入图像,但是包裹在 JPanel 内的图像根本不起作用(而且我无法向 ImageIcons 添加任何监听器,因为它们不是 GUI 元素;覆盖一个不是一个选项)。

每当用户将图像拖动到聊天客户端时,这段代码就会插入自定义 JPanel:

private void sendImage(BufferedImage im, int cl) throws IOException {
    if(output == null) return;

    //Send the image itself over to your friend
    byte[] toSend = toBytes(im, cl);
    sendString(nickname.hashCode() + "image"); //Header for image
    output.writeInt(toSend.length); //Tells how many bytes to read.
    output.write(toSend);

    //Let the user know that the image was sent
    float linmb = (float)(toSend.length / 1048576.0); //Size of file sent
    addText("\n" + nickname + " sent an image! (" + linmb + " MB)\n", Color.RED.darker());

    //Show the image itself
    DraggerPanel d = new DraggerPanel(im, true);
    text.insertComponent(d);
    d.repaint();

    //Spacer
    addText("\n");
}

这是 DraggerPanel 的源代码,这是保存图像的自定义 JPanel:

public class DraggerPanel extends JPanel {
private BufferedImage image; //The image we're drawing
private Point startingPoint = null; //Starting point for resizing
private boolean first = true; //Is this the first drag?
private boolean lockedDrag; //If true, then lock x and y to be proportionally dragged.

public DraggerPanel(BufferedImage image, boolean lockedDrag) {
    super();
    this.image = image;
    this.lockedDrag = lockedDrag;

    //The listener for dragging events.
    addMouseMotionListener(new MouseMotionListener() {
            private int inWidth = 0, inHeight = 0; //Initial height and width values
            private double ratio = 0; //Ratio of height to width for locked drag.

            public void mouseDragged(MouseEvent m) {
                if (first) { //If we're first, record initial position.
                    startingPoint = m.getPoint();
                    first = false;
                    inWidth = getWidth();
                    inHeight = getHeight();
                    ratio = (double)inHeight / inWidth;
                } else { //Otherwise, change the size of the window.
                    if (!lockedDrag) {
                        int w = (int)startingPoint.getX() - m.getX();
                        int h = (int)startingPoint.getY() - m.getY();
                        setSize(Math.abs(inWidth - w), Math.abs(inHeight - h));
                    } else {
                        int w = (int)startingPoint.getX() - m.getX();
                        int h = (int)((double)ratio * w);
                        setSize(Math.abs(inWidth - w), Math.abs(inHeight - h));
                    }
                }
                repaint();
            }

            public void mouseMoved(MouseEvent m){
            }
        });

    //Lets us know when you're not dragging anymore.
    addMouseListener(new MouseAdapter(){public void mouseReleased(MouseEvent m){first = true;}});

    //Set appropriate size.
    if(image != null) setSize(image.getWidth(), image.getHeight());
    else setSize(200,200);

    //We're live, baby.
    setVisible(true);
}

public void paint(Graphics g) {
    if (image == null) super.paint(g);
    else g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
}
}

更新1:我遵循@camickr的建议,更新了DraggerPanel以使用setPreferredSize而不是setSize,并覆盖paintComponent()而不是paint()。现在,图像具有适当的高度,但被拉伸(stretch)到 JTextPane 的宽度(这看起来就像之前所做的那样)。此外,调整大小似乎并不重要——图像根本没有改变其大小。鼠标事件肯定会发生,但不会影响大小。看来原来的问题没有完全解决,因为 JPanel 的大小不是我需要的,解决这个问题也将导致调整大小问题的解决方案。

更新2:我做到了!我终于做到了。对于遇到此问题的 future 时间旅行者,我基本上对 JTextPane 大喊大叫,不仅在我重写的 JPanel 中使用 setSize(),而且还使用 setPreferredSize() 和 setMaximumSize()。首选的与高度配合良好,而最大值则设置宽度(天知道为什么)。感谢您的提示,@camickr!

最佳答案

my components end up being squished to exactly one line of text worth of space (even though they report having a larger size).

我猜大小并不重要。

我认为您需要重写 DraggerPanel 的 getPreferredSize() 方法以返回面板的首选大小,以便文本 Pane 可以显示面板。

此外,自定义绘制是通过重写 paintComponent(...) 方法而不是 Paint() 方法来完成的。

关于java - 如何在 JTextPane 中嵌入可调整大小的 JPanel?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27092550/

相关文章:

java - 基本的 jUnit 问题

image - 如何使用imagemagick向图像添加带有一些填充的内边框?

image - Laravel 4 从 url 获取图像

java - Action Listener 检测单个事件的多个事件

java - 尝试从另一个类更改 JFrame 的背景

java - 连接到 google analytics api 时 Java 中的 SSL 异常

java - 使用 Hadoop 从 Spark 连接到 ElasticSearch 不起作用

java - 线程 "main"java.lang.StackOverflowError 中的异常与 expm

css - :before, :填充之后

java - 使用 NetBeans 自动填充 jTextField