How to move minimized components placed at the bottom of the container?

孤者浪人 提交于 2019-12-04 04:02:41

问题


I have three components in a container and buttons in it. When I hit the minimize button the components gets minimized to the bottom of the container and when I hit the minimized component then it gets maximized.

Suppose three components are lying at the bottom and if I maximize the 2nd component then it gets maximized and the 3rd minimized component does not take the position of the 2nd and this remains as space.

Screenshot

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

回答1:


I've tested this with Metal and Windows L&F, you might need to test it with some others.

Basically, when the component is invalidated and the doLayout method is called, we check for the existence of any JInternalFrame.JDesktopIcon components. We then take these and layout them out as we like...

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<Component> icons = new ArrayList<Component>(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();

            }
        }
    }
}

Make no mistake, this is a rough hack

Updated

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

To your other problem, you simply need to move the icon to a higher layer. The problem with this, is you actually need to find a layer high enough. You could use Integer.MAX_VALUE, but that's a little harsh (and you might want something over the top of the that), instead, you could calculate the maximum layer and sit +1 ontop of that...

public void doLayout() {
    super.doLayout();
    List<Component> icons = new ArrayList<Component>(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);

    }
}

You really need to take the the time to study How to use Internal Frames and How to use Layered Panes as (at least the last part) is covered in these...




回答2:


Something like that:

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


来源:https://stackoverflow.com/questions/14889369/how-to-move-minimized-components-placed-at-the-bottom-of-the-container

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!