JDesktopPaneresize

我们有一个带有两个JFrame和两个JDesktopPanes的应用程序。 我们需要将内部框架从一个框架移动到另一个框架。

我们遇到的问题是,在我们将内部框架从第一个窗口移动到第二个窗口之后,当我们调整第一个窗口的大小时,第二个窗口的内部框架也会resize。

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)单击菜单File> move 2)调整第一个窗口的大小

注意:这仅在Java 1.7中可重现。 我用的是jdk1.7.0_03。

更新:添加更多信息

这在Java 1.6(jdk1.6.0_21)上无法重现

问题是由于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); 
  • 方案二

您可能需要使用上面的“else if”条件重新编译javax.swing.plaf.basic.BasicInternalFrameUI.java并添加到rt.jar库的javax.swing.plaf.basic位置。

我已经在http://www.datafilehost.com/d/dfb7238c上附加了Java 1.7.0_25的重新编译文件

希望这可以帮助!!!

此致,尼林德拉

似乎在它处于最大状态时添加帧是罪魁祸首。 要保持第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); } 

编辑:

在阅读了Container#remove(Component c)的API之后,我得到了这个似乎有用的想法:

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