Изменение размера 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)
Ответы
Ответ 1
Проблема связана с настройкой 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 варианта:
Вам может потребоваться перекомпилировать javax.swing.plaf.basic.BasicInternalFrameUI.java с надписью "else if" и добавить в вашу библиотеку rt.jar javax.swing.plaf.basic location.
Я прикрепил перекомпилированные файлы для Java 1.7.0_25 на http://www.datafilehost.com/d/dfb7238c
Надеюсь, это поможет!!!
С уважением,
Nilindra
Ответ 2
Кажется, что добавление кадра в то время как в нем максимальное состояние является виновником. Чтобы сохранить текущий размер 1-го кадра во втором кадре, попробуйте следующее:
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);
}
EDIT:
После прочтения 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);
}
});
}