如何将最小化的JInternalFrame保持在顶部

5
我有四个内部框架和三个按钮。当我点击最大化按钮时,它会最大化,但会覆盖所有框架。但我的意思是应该显示最小化的框架。 请查看下面的代码。
  package Project;

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyVetoException;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
import javax.swing.plaf.basic.BasicInternalFrameUI;

public class Test {

    public Test() throws HeadlessException, PropertyVetoException {
        createAndShowGUI();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    new Test();
                } catch (HeadlessException ex) {
                    //Logger.getLogger(MinPanel1.class.getName()).log(Level.SEVERE, null, ex);
                } catch (PropertyVetoException ex) {
                    // Logger.getLogger(MinPanel1.class.getName()).log(Level.SEVERE, null, ex);
                }

            }
        });
    }

    private void createAndShowGUI() throws HeadlessException, PropertyVetoException {
        JFrame frame = new JFrame();
        frame.setResizable(true);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        final JDesktopPane jdp = new JDesktopPane() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(400, 400);
            }
        };

        frame.setContentPane(jdp);
        frame.pack();

        createAndAddInternalFrame(jdp, 0, 0);
        createAndAddInternalFrame(jdp, 200, 0);
        createAndAddInternalFrame(jdp, 400, 0);
        createAndAddInternalFrame(jdp, 600, 0);


        frame.setVisible(true);
    }

    private void createAndAddInternalFrame(final JDesktopPane jdp, int x, int y) throws PropertyVetoException {
        final JInternalFrame jInternalFrame = new JInternalFrame("Test1", true, true, true, true);
        jInternalFrame.setLocation(x, y);
               final JInternalFrame jInternalFrame1 = new JInternalFrame("Test2", true, true, true, true);
JPanel jp= new JPanel();
        JButton jb1 = new JButton("min");
        JButton jb2 = new JButton("[]");
        JButton jb3 = new JButton("X");

        jInternalFrame.setLayout(new GridLayout(2, 2,2,2));
        jInternalFrame1.add(jb1);
        jInternalFrame.setSize(200, 200);//testing
        jInternalFrame.setLayout(new GridLayout(2,2));

        JButton jb= new JButton("min");
       // jInternalFrame.add(jb);
      //  jInternalFrame.add(jb3);
        //jInternalFrame.add(jb2);
        jp.add(jb);
        jp.add(jb2);
        jp.add(jb3);

        jInternalFrame.add(jp);
        jb.addActionListener(new ActionListener()
                {


            @Override
            public void actionPerformed(ActionEvent ae) {
                        try {
                            jInternalFrame.setIcon(true);
                        } catch (PropertyVetoException ex) {
                        }

            }


        });
        jb1.addActionListener(new ActionListener()
                {


            @Override
            public void actionPerformed(ActionEvent ae) {
                        try {
                            jInternalFrame.setIcon(true);
                        } catch (PropertyVetoException ex) {
                        }

            }


        });
        jb2.addActionListener(new ActionListener()
        {


    @Override
    public void actionPerformed(ActionEvent ae) {
        try {
              jInternalFrame.setMaximum(true);

            }
        catch(Exception e)
        {

        }

    }


});jb3.addActionListener(new ActionListener()
{


@Override
public void actionPerformed(ActionEvent ae) {
        try {
            jInternalFrame.dispose();
        } catch (Exception ex) {
        }

}


});

        BasicInternalFrameTitlePane titlePane = (BasicInternalFrameTitlePane) ((BasicInternalFrameUI) jInternalFrame.getUI()).getNorthPane();
        jInternalFrame.remove(titlePane);


        jInternalFrame.setVisible(true);
        jInternalFrame1.setVisible(true);

        jdp.add(jInternalFrame);
                //jdp.add(jInternalFrame1);

    }
}

1
不要吞掉异常并更加小心地使用空格。 - trashgod
@trashgod 这是你的答案吗? - user2045376
一旦我修复了NPE,它就按预期工作。 - trashgod
NPE == 空指针异常 - mKorbel
@trashgod,为什么需要这个?我已经发布了运行代码,它没有给出任何错误。 - user2045376
显示剩余4条评论
2个回答

5
你可以尝试使用JDesktopPane#setComponentZOrder(Component com, int i)根据文档

移动指定组件到容器中的指定 z-order 索引。z-order 确定组件的绘制顺序;具有最高 z-order 的组件先绘制,具有最低 z-order 的组件后绘制。在组件重叠的情况下,具有较低 z-order 的组件在具有较高 z-order 的组件之上绘制。

...

注意:

并非所有平台都支持在没有调用 removeNotify 的情况下从一个容器中更改重量组件的 z-order。无法检测平台是否支持此操作,因此开发人员不应做出任何假设。

这将允许您设置包含在 JDesktopPane 中的 JInternalFrame 的顺序。

更新:

根据我的评论:

据我所见,当 JInternalFrame 处于 图标化状态 时,默认行为似乎不能通过 JDesktopPane#setComponentZOrder(Component com, int i) 进行覆盖,当其处于正常状态时可以正常工作

解决方案:

我建议调整最大化的 JInternalFrame 显示的层级:

    jb2.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            try {
                if (jInternalFrame.isMaximum()) {//restore
                    jInternalFrame.pack();
                } else {//maximize
                    jInternalFrame.setMaximum(true);
                }
                jdp.remove(jInternalFrame);
                jdp.add(jInternalFrame, JDesktopPane.FRAME_CONTENT_LAYER);
                jdp.revalidate();
                jdp.repaint();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    });

我们还不能忘记在最小化时将其添加回DEFAULT_LAYER
    jb.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            try {
                if (jInternalFrame.getLayer() == JDesktopPane.FRAME_CONTENT_LAYER) {
                    jdp.remove(jInternalFrame);
                    jdp.add(jInternalFrame, JDesktopPane.DEFAULT_LAYER);
                    jdp.revalidate();
                    jdp.repaint();
                }
                jInternalFrame.pack();
                jInternalFrame.setIcon(true);
            } catch (PropertyVetoException ex) {
            }

        }
    });

这是完整的代码:

在此输入图片描述

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyVetoException;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
import javax.swing.plaf.basic.BasicInternalFrameUI;

public class Test {

    public Test() throws HeadlessException, PropertyVetoException {
        createAndShowGUI();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    new Test();
                } catch (HeadlessException ex) {
                    ex.printStackTrace();
                } catch (PropertyVetoException ex) {
                    ex.printStackTrace();
                }

            }
        });
    }

    private void createAndShowGUI() throws HeadlessException, PropertyVetoException {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        final JDesktopPane jdp = new JDesktopPane() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(600, 400);
            }
        };

        frame.setContentPane(jdp);
        frame.pack();

        createAndAddInternalFrame(jdp, 0, 0);
        createAndAddInternalFrame(jdp, 300, 0);
        createAndAddInternalFrame(jdp, 0, 200);

        frame.setVisible(true);
    }

    private void createAndAddInternalFrame(final JDesktopPane jdp, int x, int y) throws PropertyVetoException {
        final JInternalFrame jInternalFrame = new JInternalFrame("Test1", true, true, true, true);
        jInternalFrame.setLocation(x, y);

        JPanel jp = new JPanel();

        JButton jb = new JButton("min");
        JButton jb2 = new JButton("max/restore");
        JButton jb3 = new JButton("close");

        jInternalFrame.setLayout(new GridLayout(2, 2));

        jp.add(jb);
        jp.add(jb2);
        jp.add(jb3);

        jInternalFrame.add(jp);

        jb.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                try {
                    if (jInternalFrame.getLayer() == JDesktopPane.FRAME_CONTENT_LAYER) {
                        jdp.remove(jInternalFrame);
                        jdp.add(jInternalFrame, JDesktopPane.DEFAULT_LAYER);
                        jdp.revalidate();
                        jdp.repaint();
                    }
                    jInternalFrame.pack();
                    jInternalFrame.setIcon(true);
                } catch (PropertyVetoException ex) {
                    ex.printStackTrace();
                }

            }
        });
        jb2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                try {
                    if (jInternalFrame.isMaximum()) {//restore
                        jInternalFrame.pack();
                    } else {//maximize
                        jInternalFrame.setMaximum(true);
                    }
                    jdp.remove(jInternalFrame);
                    jdp.add(jInternalFrame, JDesktopPane.FRAME_CONTENT_LAYER);
                    jdp.revalidate();
                    jdp.repaint();
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        });
        jb3.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                try {
                    jInternalFrame.dispose();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }

            }
        });

        BasicInternalFrameTitlePane titlePane = (BasicInternalFrameTitlePane) ((BasicInternalFrameUI) jInternalFrame.getUI()).getNorthPane();
        jInternalFrame.remove(titlePane);

        jInternalFrame.pack();
        jInternalFrame.setVisible(true);

        jdp.add(jInternalFrame);
    }
}

i的值会是多少? - user2045376
@sukant 容器中的索引,即任何小于最大化索引值的内容应该在其后绘制。 - David Kroukamp
如果我将索引值设为零,那么它才能正常工作。对于其他值,它会产生运行时错误。代码可以运行零值,但我的期望输出没有出现。所以我问了一下i的值应该是多少。 - user2045376
1
+1 我无法使 setComponentZOrder() 正常工作,但这是一种有教育意义的方法。 - trashgod
@sukant:举个例子,我的平台的UI代理InternalFrameUI没有BasicInternalFrameTitlePane,因此会出现NPE。 - trashgod
显示剩余2条评论

4
这是在最大化按钮处理程序中调用 moveToBack() 的结果。同时请记得在内部框架上调用 pack()
附注:我已更新示例,包括 maxminicon 按钮。为了更加方便测试,按钮使用 Action,而内部框架具有不同的名称。参见 createToolBar() 以动态更改 L&F,例如。
frame.add(createToolBar(frame), BorderLayout.NORTH);

image

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.beans.PropertyVetoException;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

//* @see https://dev59.com/MW7Xa4cB1Zd3GeqPqHYz#14874924 */
public class Test {

    public Test() {
        createAndShowGUI();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new Test();
            }
        });
    }

    private void createAndShowGUI() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JDesktopPane jdp = new JDesktopPane() {

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(600, 400);
            }
        };
        for (int i = 0; i < 4; i++) {
            createInternalFrame(jdp, 100 * i, 100 * i);
        }
        frame.add(jdp);
        frame.pack();
        frame.setVisible(true);
    }

    private void createInternalFrame(final JDesktopPane jdp, int x, int y) {
        final JInternalFrame jif = new JInternalFrame("Test" + x, true, true, true, true);
        jif.setLocation(x, y);
        JPanel jp = new JPanel();
        jp.add(new JButton(new AbstractAction("max") {

            @Override
            public void actionPerformed(ActionEvent ae) {
                try {
                    jif.setMaximum(true);
                    jif.moveToBack();
                } catch (PropertyVetoException e) {
                    e.printStackTrace();
                }

            }
        }));
        jp.add(new JButton(new AbstractAction("min") {

            @Override
            public void actionPerformed(ActionEvent ae) {
                try {
                    jif.setMaximum(false);
                } catch (PropertyVetoException e) {
                    e.printStackTrace();
                }

            }
        }));
        jp.add(new JButton(new AbstractAction("icon") {

            @Override
            public void actionPerformed(ActionEvent ae) {
                try {
                    jif.setIcon(true);
                } catch (PropertyVetoException e) {
                    e.printStackTrace();
                }
            }
        }));
        jif.add(jp);
        jif.pack();
        jif.setVisible(true);
        jdp.add(jif);
    }
}

我已经重构了你的 sscce 以便更加专注于解决问题并且使实验更容易进行。 - trashgod
@trashgod,我已经编写了一段满足我的需求的代码,但是在三个面板中只有一个面板起作用。您能否帮我找出错误所在?如果可以,请告诉我,这样我就可以在这里发布代码了。 - user2045376
@DavidKroukamp,我的问题被删除了,是谁做的? - user2045376
1
@sukant:抱歉,DYM是“你是不是想说”的意思。除了标签之外,只有您编辑了这个问题,我不确定它是否被删除了。 - trashgod

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接