1

In the SSCCE below, you can see that if you maximize one of the JInternalFrames, then it maximizes them both. This only (AFAIK) happens with the "Windows" LookAndFeel (if you omit the LookAndFeel code, it works as expected).

To reproduce:

  1. Run the SSCCE below.
  2. Maximize one of the JInternalFrames.
  3. Close (X) the one you maximized
  4. Observe the other one was maximized as well.

Is there any way to stop this behavior? Is this a bug?

SSCCE:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;

class Test2 {
    public static void main(String[] args) {
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Windows".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }
        JFrame frame = new JFrame();
        JDesktopPane jdp = new JDesktopPane();
        jdp.setBackground(Color.gray);
        frame.add(jdp);
        jdp.setVisible(true);
        frame.setExtendedState(frame.getExtendedState()|JFrame.MAXIMIZED_BOTH );
        frame.setVisible(true);

        JInternalFrame jiffy1 = new JInternalFrame("Jiffy1", true, true, true, true);
        jdp.add(jiffy1);
        JLabel jiffy1_label = new JLabel("Jiffy1");
        jiffy1_label.setHorizontalAlignment(SwingConstants.CENTER);
        jiffy1_label.setFont(new Font("Tahoma", 0, 50));
        jiffy1.add(jiffy1_label);
        jiffy1.setPreferredSize(new Dimension(300,300));
        jiffy1.setVisible(true);
        jiffy1.pack();
        centerJIF(jdp, jiffy1);

        JInternalFrame jiffy2 = new JInternalFrame("Jiffy2", true, true, true, true);
        jdp.add(jiffy2);
        JLabel jiffy2_label = new JLabel("Jiffy2");
        jiffy2_label.setHorizontalAlignment(SwingConstants.CENTER);
        jiffy2_label.setFont(new Font("Tahoma", 0, 50));
        jiffy2.add(jiffy2_label);
        jiffy2.setPreferredSize(new Dimension(200,200));
        jiffy2.setVisible(true);
        jiffy2.pack();
        centerJIF(jdp, jiffy2);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private static void centerJIF(JDesktopPane jdp, JInternalFrame jiffy) {
        Dimension desktopSize = jdp.getSize();
        Dimension VInternalFrameSize = jiffy.getSize();
        int width = (desktopSize.width - VInternalFrameSize.width) / 2;
        int height = (desktopSize.height - VInternalFrameSize.height) / 2;
        jiffy.setLocation(width, height);
    }
}
4

1 回答 1

2

在 Windows DesktopManager 中有一个功能(在我看来是一个错误......),当您最大化一帧时,它会最大化所有帧。

来自第 62 行的WindowsDesktopManager.java (Java 7)

... 
public void activateFrame(JInternalFrame f) {
    JInternalFrame currentFrame = currentFrameRef != null ? 
        currentFrameRef.get() : null;
    try {
        super.activateFrame(f);
        if (currentFrame != null && f != currentFrame) {
            // If the current frame is maximized, transfer that 
            // attribute to the frame being activated.
            if (currentFrame.isMaximum() &&
        (f.getClientProperty("JInternalFrame.frameType") !=
        "optionDialog") ) {
                //Special case.  If key binding was used to select next
                //frame instead of minimizing the icon via the minimize
                //icon.
                if (!currentFrame.isIcon()) {
                    currentFrame.setMaximum(false);
                    if (f.isMaximizable()) {
                        if (!f.isMaximum()) {
                            f.setMaximum(true);
                        } else if (f.isMaximum() && f.isIcon()) {
                            f.setIcon(false);
                        } else {
                            f.setMaximum(false);
                        }
                    }
                }
            }
            if (currentFrame.isSelected()) {
                currentFrame.setSelected(false);
            }
        }

        if (!f.isSelected()) {
            f.setSelected(true);
        }
    } catch (PropertyVetoException e) {}
    if (f != currentFrame) {
        currentFrameRef = new WeakReference(f);
    }
}
...

因此您可以重新安装 DefaultDesktopManager 而不是 WindowsDesktopManager 并解决问题:

JDesktopPane jdp = new JDesktopPane();
jdp.setDesktopManager(new DefaultDesktopManager());
于 2014-06-19T16:18:52.580 回答