JDesktopPane изменить размер

У нас есть приложение с двумя JFrames с двумя JDesktopPanes. Нам нужно переместить внутреннюю рамку из одной рамки в другую.

Проблема заключается в том, что после перемещения внутренней рамки из первого окна во второе окно, когда мы изменяем размер первого окна, внутренняя рамка второго окна также изменяется.

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




  }
}

В приведенном выше примере приложения, чтобы воспроизвести 1) щелкните меню «Файл»> «Переместить» 2) измените размер первого окна.

ПРИМЕЧАНИЕ. Это можно воспроизвести только в Java 1.7. Я использую jdk1.7.0_03.

Обновление: добавьте больше информации

Это не воспроизводилось на Java 1.6 (jdk1.6.0_21)


person Nethru    schedule 28.08.2013    source источник
comment
интересно, наверное баг +1   -  person mKorbel    schedule 28.08.2013
comment
+1 Я удалил свой первоначальный ответ, так как не прочитал вопрос должным образом. Однако с тех пор я заменил его обходным путем.   -  person splungebob    schedule 28.08.2013


Ответы (2)


Проблема связана с настройкой Java 7 реализации javax.swing.plaf.basic.BasicInternalFrameUI.

  • Код Java 1.6

    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

    public void propertyChange (PropertyChangeEvent evt) {

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

    ПРИМЕЧАНИЕ. Условие else if было удалено. Это виновник.

Я предлагаю вам 2 варианта:

  • Вариант первый

    JInternalFrame selectedFrame = desktopPane.getSelectedFrame();
    desktopPane.remove(selectedFrame);
    desktopPane.repaint();
    
    secondFrame.updateUI(); // The magic part, less expensive execution.
    
    secondFrame.addInternalFrame(selectedFrame);
    
  • Вариант второй

Возможно, вам придется перекомпилировать javax.swing.plaf.basic.BasicInternalFrameUI.java с указанным выше условием «иначе, если» и добавить в папку javax.swing.plaf.basic вашей библиотеки rt.jar.

Я прикрепил перекомпилированные файлы для Java 1.7.0_25 по адресу http://www.datafilehost.com/d/dfb7238c

Надеюсь это поможет!!!

С уважением, Нилиндра

person Nilindra Fernando    schedule 02.09.2013

Кажется, что добавление кадра в максимальном состоянии является виновником. Чтобы сохранить текущий размер от 1-го кадра до 2-го кадра, попробуйте следующее:

public void moveFrame()
{
  JInternalFrame selectedFrame = desktopPane.getSelectedFrame();
  Dimension currentSize = selectedFrame.getSize();
  try
  {
    selectedFrame.setMaximum(false);
  }
  catch (PropertyVetoException ex)
  {
    ex.printStackTrace();
  }
  selectedFrame.setSize(currentSize);

  desktopPane.remove(selectedFrame);
  desktopPane.repaint();
  secondFrame.addInternalFrame(selectedFrame);
}

ИЗМЕНИТЬ:

После прочтения API для Container#remove(Component c) у меня появилась идея, которая, кажется, работает:

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

  desktopPane.remove(selectedFrame);
  desktopPane.repaint();
  SwingUtilities.updateComponentTreeUI(selectedFrame);

  SwingUtilities.invokeLater(new Runnable()
  {
    public void run()
    {
      secondFrame.addInternalFrame(selectedFrame);
    }
  });
}
person splungebob    schedule 28.08.2013
comment
Но проблема сохраняется после того, как вы развернете внутреннюю рамку во втором окне. Это не воспроизводилось в java 1.6. - person Nethru; 29.08.2013
comment
@Nethru: см. мой РЕДАКТИРОВАТЬ. - person splungebob; 30.08.2013
comment
Обновление. Основываясь на вашем решении, изучив его дальше, я обнаружил, что вызов updateUI() для выбранного InternalFrame также помог. выбранныйFrame.updateUI(); - person Nethru; 02.09.2013