Search code examples
javaswingjinternalframejdesktoppane

JDesktopPane resize


We have a application with two JFrames with two JDesktopPanes. We need to move an internal frame from one frame to another.

The problem we have is that after we move the internalframe from first window to the second window, when we resize the fist window, the internal frame of the second window also gets resized.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyVetoException;

import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

class FirstFrame extends JFrame
{
  JDesktopPane desktopPane = new JDesktopPane();

  SecondFrame secondFrame;

  public FirstFrame(SecondFrame secondFrame)
  {
    this.secondFrame = secondFrame;
    setTitle("FirstFrame example");
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    add(desktopPane);

    JMenuBar menuBar = new JMenuBar();
    JMenu menu = new JMenu("File");
    JMenuItem item = new JMenuItem("Move");

    item.addActionListener(new ActionListener()
    {

      @Override
      public void actionPerformed(ActionEvent actionevent)
      {
        moveFrame();
      }
    });

    menu.add(item);
    menuBar.add(menu);
    setJMenuBar(menuBar);

  }

  public void addAnInternalFrame()
  {
    JInternalFrame frame = new JInternalFrame();
    frame.setTitle("An Internal Frame");

    desktopPane.add(frame);
    frame.setVisible(true);
    frame.setMaximizable(true);
    try
    {
      frame.setSelected(true);
      frame.setMaximum(true);
    }
    catch (PropertyVetoException e)
    {
      e.printStackTrace();
    }

  }

  public void moveFrame()
  {
    JInternalFrame selectedFrame = desktopPane.getSelectedFrame();
    desktopPane.remove(selectedFrame);
    desktopPane.repaint();

    secondFrame.addInternalFrame(selectedFrame);
  }
}

class SecondFrame extends JFrame
{
  JDesktopPane desktopPane = new JDesktopPane();

  public SecondFrame()
  {
    setTitle("SecondFrame example");
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    add(desktopPane);
  }

  public void addInternalFrame(JInternalFrame frame)
  {
    desktopPane.add(frame);
  }
}

public class DesktopPaneExample
{
  public static void main(String args[]) throws PropertyVetoException
  {

    SecondFrame secondFrame = new SecondFrame();

    FirstFrame firstFrame = new FirstFrame(secondFrame);

    firstFrame.setSize(400, 400);
    firstFrame.setLocation(100, 100);
    firstFrame.setVisible(true);
    firstFrame.addAnInternalFrame();

    secondFrame.setSize(400, 400);
    secondFrame.setLocation(520, 100);
    secondFrame.setVisible(true);




  }
}

In the above sample application, to reproduce 1) click menu File>move 2) resize the first window

NOTE: This is reproducable in Java 1.7 only. I use jdk1.7.0_03.

Update: add more information

This was not reproducible on Java 1.6 (jdk1.6.0_21)


Solution

  • The issue is due to Java 7's tweaking on javax.swing.plaf.basic.BasicInternalFrameUI implementation.

    • Java 1.6 Code

      public void propertyChange(PropertyChangeEvent evt) {

              if ((frame.getParent() != null) && !componentListenerAdded) {
                  f.getParent().addComponentListener(componentListener);
                  componentListenerAdded = true;
              } else if ((newValue == null) && componentListenerAdded) {
                  if (f.getParent() != null) {
                      f.getParent()
                              .removeComponentListener(componentListener);
                  }
                  componentListenerAdded = false;
              }
      
    • Java 1.7 Code

      public void propertyChange(PropertyChangeEvent evt) {

              if ((frame.getParent() != null) && !componentListenerAdded) {
                  f.getParent().addComponentListener(componentListener);
                  componentListenerAdded = true;
              }
      

      NOTE: The else if condition was removed. This is the culprit.

    I suggest you 2 options:

    • Option one

      JInternalFrame selectedFrame = desktopPane.getSelectedFrame();
      desktopPane.remove(selectedFrame);
      desktopPane.repaint();
      
      secondFrame.updateUI(); // The magic part, less expensive execution.
      
      secondFrame.addInternalFrame(selectedFrame);
      
    • Option two

    You may need to recompile javax.swing.plaf.basic.BasicInternalFrameUI.java with above "else if" condition and add to your rt.jar library's javax.swing.plaf.basic location.

    I have attached the recompiled files for Java 1.7.0_25 at http://www.datafilehost.com/d/dfb7238c

    Hope this helps!!!

    Regards, Nilindra