如何移动放置在容器底部的最小化组件?

我在容器中有三个组件,其中有按钮。 当我点击最小化按钮时,组件最小化到容器的底部,当我点击最小化的组件时,它会被最大化。

假设三个组件位于底部,如果我最大化第二个组件,那么它将获得最大化,第三个最小化组件不会占据第二个组件的位置,这仍然是空间。

截图
在此处输入图像描述

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.JLabel; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.plaf.basic.BasicInternalFrameTitlePane; import javax.swing.plaf.basic.BasicInternalFrameUI; public class Test2 { public Test2() throws HeadlessException, PropertyVetoException { createAndShowGUI(); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { try { new Test2(); } 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, 1, 200); frame.setVisible(true); } private void createAndAddInternalFrame(final JDesktopPane jdp, int x, int y) throws PropertyVetoException { final JInternalFrame jInternalFrame = new JInternalFrame("", true, true, true, true); jInternalFrame.setLocation(x, y); JPanel jp = new JPanel(); JLabel jl=new JLabel("panel"+x); JButton jb = new JButton("_"); JButton jb2 = new JButton("[]"); JButton jb3 = new JButton("X"); jInternalFrame.setLayout(new GridLayout(2, 2)); jp.add(jl); 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.repaint(); jdp.add(jInternalFrame); } } 

我用Metal和Windows L&F对此进行了测试,您可能需要与其他一些测试它。

基本上,当组件失效并调用doLayout方法时,我们检查是否存在任何JInternalFrame.JDesktopIcon组件。 然后我们采取这些并按照我们的意愿布置它们……

 public class TestInternalFrame { public static void main(String[] args) { new TestInternalFrame(); } private int xpos = 0; private int ypos = 0; public TestInternalFrame() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception exp) { exp.printStackTrace(); } DesktopPane pane = new DesktopPane(); pane.add(newInternalFrame()); pane.add(newInternalFrame()); pane.add(newInternalFrame()); JFrame frame = new JFrame(); frame.add(pane); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(400, 400); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public JInternalFrame newInternalFrame() { JInternalFrame inf = new JInternalFrame("Blah", true, true, true, true); inf.setLocation(xpos, ypos); inf.setSize(100, 100); inf.setVisible(true); xpos += 50; ypos += 50; return inf; } public class DesktopPane extends JDesktopPane { @Override public void doLayout() { super.doLayout(); List icons = new ArrayList(25); for (Component comp : getComponents()) { if (comp instanceof JInternalFrame.JDesktopIcon) { icons.add(comp); } } int x = 0; for (Component icon : icons) { int y = getHeight() - icon.getHeight(); icon.setLocation(x, y); x += icon.getWidth(); } } } } 

毫无疑问,这是一个粗糙的黑客

更新

 int x = 0; for (Component icon : icons) { int y = getHeight() - icon.getHeight(); icon.setLocation(x, y); x += icon.getWidth(); setLayer(icon, 10); // <--- Add me } 

对于您的其他问题,您只需将图标移动到更高层。 这个问题,你实际上需要找到一个足够高的层。 你可以使用Integer.MAX_VALUE ,但这有点苛刻(你可能想要一些超过它的顶部),相反,你可以计算最大层并坐在那里......

 public void doLayout() { super.doLayout(); List icons = new ArrayList(25); int maxLayer = 0; for (Component comp : getComponents()) { if (comp instanceof JInternalFrame.JDesktopIcon) { icons.add(comp); maxLayer = Math.max(getLayer(comp), maxLayer); } } maxLayer++; int x = 0; for (Component icon : icons) { int y = getHeight() - icon.getHeight(); icon.setLocation(x, y); x += icon.getWidth(); setLayer(icon, maxLayer); } } 

你真的需要花时间研究如何使用内部框架和如何使用分层窗格 (至少最后一部分)涵盖在这些...

像这样的东西:

 jdp.setDesktopManager( new DefaultDesktopManager(){ @Override public void deiconifyFrame(JInternalFrame f) { super.deiconifyFrame(f); JDesktopPane d = f.getDesktopPane(); JInternalFrame[] frames = d.getAllFrames(); for(JInternalFrame frame : frames ) { Rectangle bounds = getBoundsForIconOf(frame); // relayout all frames } } });