2014-11-23 38 views
1

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

足够方便的是,JTextPane中有一个相关的方法:insertComponent(Component c),但是每当我使用它时,我的组件最终都会压缩到恰好一行文本的空间值(尽管它们报告有更大的尺寸)。这对于简单的按钮来说是完美的,但是如果我需要更大的东西,我会很失败。我可以通过ImageIcons自己插入图像,但是包装在JPanel中的图像根本不起作用(另外我不能将任何侦听器添加到ImageIcons中,因为它们不是GUI元素;覆盖一个不是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()。现在,图像具有适当的高度,但被拉伸到JTextPane的宽度(这看起来就像之前做的那样)。此外,调整大小似乎并不重要 - 图像的大小根本不会改变。鼠标事件肯定会经过,但不会影响大小。看起来好像原始问题没有完全解决,因为JPanel的大小并不是我所需要的,解决方案也将导致解决调整大小问题。

更新2:我做到了!我终于做到了。对于有这个问题的旅行者来说,我基本上在JTextPane上大吼大叫,不仅在我重写的JPanel中使用setSize(),而且还使用setPreferredSize()和setMaximumSize()。首选的一个可以很好地适应高度,而最大的设置宽度(上帝知道为什么)。感谢您的提示,@camickr!

回答

0

我的组件最终被压缩到恰好一行文本的空间值(即使它们报告具有较大的大小)。

我猜想大小并不重要。

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

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

+0

非常感谢你为我设定正确的思路。更新主要帖子的结果。 :) – rushingseas 2014-11-24 06:33:13