2014-11-23 3 views
1

Существует много вопросов об обратном, вставляя JTextPane в JPanel. Это не мой вопрос. Мне нужно иметь возможность вставлять пользовательский JPanel (с перетаскиванием, перетаскиванием мышью и мышью) в JTextPane, который затем помещается в JScrollPane и, наконец, помещается в JFrame для отображения. Причина в том, что мне нужно иметь изображение с поддержкой изменения размера, перетащив его в клиентский чат, который сам по себе является главным текстом.Как вы вставляете изменяемый JPanel внутри JTextPane?

Удобно, что в 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(). Теперь изображение имеет правильную высоту, но растянуто до ширины JTextPane (что похоже на то, что он делал раньше). Кроме того, изменение размера не кажется существенным - изображение не меняет его размер вообще. События мыши определенно проходят, но не влияют на размер. Похоже, что первоначальная проблема не полностью решена, так как размер JPanel не то, что мне нужно, и решение этого также приведет к решению проблемы изменения размера.

Обновление 2: Я сделал это! Наконец я это сделал. Для будущих путешественников, у которых есть эта проблема, я в основном кричал на JTextPane, не только используя setSize() в моем переопределенном JPanel, но также setPreferredSize() и setMaximumSize(). Предпочтительный вариант хорошо работает с высотой, а максимальная устанавливает ширину (Бог знает, почему). Спасибо за ваши советы, @camickr!

ответ

0

мои компоненты в конечном итоге сжимаются ровно на одну строку текста (хотя они сообщают о большем размере).

Я бы предположил, что размер не имеет значения.

Я бы подумал, что вам нужно переопределить метод DraggerPanel, чтобы вернуть желаемый размер панели, чтобы панель текста отображала панель.

Кроме того, обычная окраска выполняется путем переопределения метода paintComponent(...) NOT методом paint().

+0

Огромное спасибо за то, что поставили меня на правильном пути мысли. Обновлено основное сообщение с результатами. :) – rushingseas

Смежные вопросы