繁体   English   中英

JPanel中的JPanel太多(使用GridBagLayout)

[英]Too many JPanels inside a JPanel (with GridBagLayout)

所以基本上如果我把JPanel放在一个使用GridBagLayoutJPanel ,我用setPreferredSize限制大小,最终它达到了无法容纳所有这些的点,并且它展示了附图中显示的行为:

在此输入图像描述

我正在制作手风琴 这只是一个展示我遇到的问题的例子。 手风琴的每个部分都可以单独打开,它们具有任意大小,可以随时添加。 它很容易达到所有单个面板的高度,并将它们与总高度进行比较,但是当添加太多时,它表现出我所展示的嘎吱嘎吱的行为。 这也缩小了高度,因此更难以确定何时发生嘎吱嘎吱声。 我必须缓存高度,并以某种方式预先计算新部件的高度。 最终目标是在添加新面板并且没有足够空间时移除旧面板。

有没有一种简单的方法来确定如果它没有受到限制会有什么高度,或者可能是一种支持的方法来检测何时发生这样的嘎吱嘎吱(所以我可以在再次涂漆之前快速将其稀释)? 使GridBagLayout像其他布局一样运行并且溢出到Hammerspace而不是压缩的选项也可以工作。

代码例如:

import java.awt.*;
import java.awt.event.*;
import javaisms.out;
import javax.swing.*;

public class FoldDrag extends JLayeredPane {
    public TexturedPanel backingPanel = new TexturedPanel(new GridBagLayout(),"data/gui/grayerbricks.png");
    static JPanel windowbase=new JPanel();
    static JPanel restrictedpanel=new JPanel(new GridBagLayout());

    GridBagConstraints gbc = new GridBagConstraints();

    public FoldDrag() {
        JButton addpan  = new JButton("Add things");
        windowbase.add(addpan);
        windowbase.add(restrictedpanel);
        restrictedpanel.setBackground(Color.red);
        restrictedpanel.setPreferredSize(new Dimension(200,200));
        gbc.weighty=1;
        gbc.weightx=1;
        gbc.gridx=0;
        gbc.gridy=0;
        gbc.gridheight=1;
        gbc.gridwidth=1;
        gbc.fill=GridBagConstraints.HORIZONTAL;
        addpan.addActionListener(new ActionListener() {
            int number=0;
            @Override
            public void actionPerformed(ActionEvent e)
            {
                number++;
                gbc.gridy=number;
                JPanel tmppanel = new JPanel();
                tmppanel.setPreferredSize(new Dimension(100,30));
                if(number%3==0)
                    tmppanel.setBackground(Color.blue);
                if(number%3==1)
                    tmppanel.setBackground(Color.yellow);
                if(number%3==2)
                    tmppanel.setBackground(Color.green);
                restrictedpanel.add(tmppanel,gbc);
                restrictedpanel.validate();
            }
        });
        windowbase.setVisible(true);
    }
    private static void createAndShowUI() {
        JFrame frame = new JFrame("DragLabelOnLayeredPane");
        frame.getContentPane().add(windowbase);
        FoldDrag thedrag=new FoldDrag();
        windowbase.add(thedrag);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(300,300));
        frame.pack();
        frame.setResizable(true);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        out.active=true;
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                createAndShowUI();
            }
        });
    }
}

编辑:似乎我没有很好地描述我的手风琴版本。 这是一个链接

您有特殊的要求,通过使用它的布局管理器可以更好地服务。 这使您能够控制布局的各个方面,而无需诉诸黑客或“解决方法”,这些工作从未完全奏效或具有奇怪的副作用

手风琴布局

public class AccordionLayout implements LayoutManager {

    // This "could" be controlled by constraints, but that would assume
    // that more then one component could be expanded at a time
    private Component expanded;

    public void setExpanded(Component expanded) {
        this.expanded = expanded;
    }

    public Component getExpanded() {
        return expanded;
    }

    @Override
    public void addLayoutComponent(String name, Component comp) {
    }

    @Override
    public void removeLayoutComponent(Component comp) {
    }

    @Override
    public Dimension preferredLayoutSize(Container parent) {
        Dimension size = minimumLayoutSize(parent);
        if (expanded != null) {
            size.height -= expanded.getMinimumSize().height;
            size.height += expanded.getPreferredSize().height;
        }

        return size;
    }

    @Override
    public Dimension minimumLayoutSize(Container parent) {
        int height = 0;
        int width = 0;
        for (Component comp : parent.getComponents()) {
            width = Math.max(width, comp.getPreferredSize().width);
            height += comp.getMinimumSize().height;
        }
        return new Dimension(width, height);
    }

    @Override
    public void layoutContainer(Container parent) {

        Insets insets = parent.getInsets();
        int availableHeight = parent.getHeight() - (insets.top + insets.bottom);
        int x = insets.left;
        int y = insets.top;

        int maxSize = 0;
        Dimension minSize = minimumLayoutSize(parent);
        if (expanded != null) {
            minSize.height -= expanded.getMinimumSize().height;
            // Try an honour the preferred size the expanded component...
            maxSize = Math.max(expanded.getPreferredSize().height, availableHeight - minSize.height);
        }

        int width = parent.getWidth() - (insets.left + insets.right);
        for (Component comp : parent.getComponents()) {
            if (expanded != comp) {
                comp.setSize(width, comp.getMinimumSize().height);
            } else {
                comp.setSize(width, maxSize);
            }
            comp.setLocation(x, y);
            y += comp.getHeight();
        }

    }

}

可运行的例子......

这就是enth度,创建一个专门的组件来充当每个“折叠”,但这只是从外部降低了API的复杂性,这意味着,你只需要考虑标题和内容,然后让剩下的API会照顾好自己

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private AccordionLayout layout;

        public TestPane() {
            layout = new AccordionLayout();
            setLayout(layout);

            AccordionListener listener = new AccordionListener() {
                @Override
                public void accordionSelected(Component comp) {
                    layout.setExpanded(comp);
                    revalidate();
                    repaint();
                }
            };

            Color colors[] = {Color.RED, Color.BLUE, Color.CYAN, Color.GREEN, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.YELLOW};
            String titles[] = {"Red", "Blue", "Cyan", "Green", "Magenta", "Orange", "Pink", "Yellow"};
            for (int index = 0; index < colors.length; index++) {
                AccordionPanel panel = new AccordionPanel(titles[index], new ContentPane(colors[index]));
                panel.setAccordionListener(listener);
                add(panel);
            }
        }

    }

    public class ContentPane extends JPanel {

        public ContentPane(Color background) {
            setBackground(background);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(100, 100);
        }

    }

    public interface AccordionListener {

        public void accordionSelected(Component comp);

    }

    public class AccordionPanel extends JPanel {

        private JLabel title;
        private JPanel header;
        private Component content;

        private AccordionListener accordionListener;

        public AccordionPanel() {
            setLayout(new BorderLayout());

            title = new JLabel("Title");

            header = new JPanel(new FlowLayout(FlowLayout.LEADING));
            header.setBackground(Color.GRAY);
            header.setBorder(new LineBorder(Color.BLACK));
            header.add(title);
            add(header, BorderLayout.NORTH);

            header.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    AccordionListener listener = getAccordionListener();
                    if (listener != null) {
                        listener.accordionSelected(AccordionPanel.this);
                    }
                }
            });
        }

        public AccordionPanel(String title) {
            this();
            setTitle(title);
        }

        public AccordionPanel(String title, Component content) {
            this(title);
            setContentPane(content);
        }

        public void setAccordionListener(AccordionListener accordionListener) {
            this.accordionListener = accordionListener;
        }

        public AccordionListener getAccordionListener() {
            return accordionListener;
        }

        public void setTitle(String text) {
            title.setText(text);
            revalidate();
        }

        public String getText() {
            return title.getText();
        }

        public void setContentPane(Component content) {
            if (this.content != null) {
                remove(this.content);
            }

            this.content = content;
            if (this.content != null) {
                add(this.content);
            }
            revalidate();
        }

        public Component getContent() {
            return content;
        }

        @Override
        public Dimension getMinimumSize() {
            return header.getPreferredSize();
        }

        @Override
        public Dimension getPreferredSize() {
            Dimension size = content != null ? content.getPreferredSize() : super.getPreferredSize();
            Dimension min = getMinimumSize();
            size.width = Math.max(min.width, size.width);
            size.height += min.height;
            return size;
        }

    }

    public class AccordionLayout implements LayoutManager {

        // This "could" be controled by constraints, but that would assume
        // that more then one component could be expanded at a time
        private Component expanded;

        public void setExpanded(Component expanded) {
            this.expanded = expanded;
        }

        public Component getExpanded() {
            return expanded;
        }

        @Override
        public void addLayoutComponent(String name, Component comp) {
        }

        @Override
        public void removeLayoutComponent(Component comp) {
        }

        @Override
        public Dimension preferredLayoutSize(Container parent) {
            Dimension size = minimumLayoutSize(parent);
            if (expanded != null) {
                size.height -= expanded.getMinimumSize().height;
                size.height += expanded.getPreferredSize().height;
            }

            return size;
        }

        @Override
        public Dimension minimumLayoutSize(Container parent) {
            int height = 0;
            int width = 0;
            for (Component comp : parent.getComponents()) {
                width = Math.max(width, comp.getPreferredSize().width);
                height += comp.getMinimumSize().height;
            }
            return new Dimension(width, height);
        }

        @Override
        public void layoutContainer(Container parent) {

            Insets insets = parent.getInsets();
            int availableHeight = parent.getHeight() - (insets.top + insets.bottom);
            int x = insets.left;
            int y = insets.top;

            int maxSize = 0;
            Dimension minSize = minimumLayoutSize(parent);
            if (expanded != null) {
                minSize.height -= expanded.getMinimumSize().height;
                // Try an honour the preferred size the expanded component...
                maxSize = Math.max(expanded.getPreferredSize().height, availableHeight - minSize.height);
            }

            int width = parent.getWidth() - (insets.left + insets.right);
            for (Component comp : parent.getComponents()) {
                if (expanded != comp) {
                    comp.setSize(width, comp.getMinimumSize().height);
                } else {
                    comp.setSize(width, maxSize);
                }
                comp.setLocation(x, y);
                y += comp.getHeight();
            }

        }

    }

}

现在,如果你真的想要挑战,你可以使用一些动画布局代理,并做一些像...

动画布局

最终目标是在添加新面板并且没有足够空间时移除旧面板

我猜想在添加一个面板后,你可以将首选高度与实际高度进行比较。 当首选高度较大时,您遇到问题,并根据需要删除组件。

那么接下来的问题是使用不改变面板高度的布局管理器。 这仍然可以通过GridBagLayout完成。 您只需要覆盖getMinimumSize()方法以返回getPreferredSize()维度。

手风琴的每个部分都可以单独打开,它们具有任意大小,可以随时添加

您可能需要考虑使用相对布局 您可以添加其首选大小将受到尊重的组件。 因此,您可以检查首选高度何时大于实际高度。

然后,您还可以添加将根据面板中剩余的空间量调整大小的组件。 这些将是你的扩展面板。

因此,在您的示例中,您展示项目时的示例可以将该组件配置为占用整个可用空间。 如果展开两个项目,那么每个项目将获得一半的可用空间。

也许是这样的:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ExpandingPanel extends JPanel
{
    private JPanel expanding;

    public ExpandingPanel(String text, Color color)
    {
        setLayout( new BorderLayout() );

        JButton button = new JButton( text );
        add(button, BorderLayout.NORTH);

        expanding = new JPanel();
        expanding.setBackground( color );
        expanding.setVisible( false );
        add(expanding, BorderLayout.CENTER);

        button.addActionListener( new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                expanding.setVisible( !expanding.isVisible() );

                Container parent = ExpandingPanel.this.getParent();
                LayoutManager2 layout = (LayoutManager2)parent.getLayout();

                if (expanding.isVisible())
                    layout.addLayoutComponent(ExpandingPanel.this, new Float(1));
                else
                    layout.addLayoutComponent(ExpandingPanel.this, null);

                revalidate();
                repaint();
            }
        });
    }

    private static void createAndShowGUI()
    {
        RelativeLayout rl = new RelativeLayout(RelativeLayout.Y_AXIS);
        rl.setFill( true );

        JPanel content = new JPanel( rl );
        content.add( new ExpandingPanel("Red", Color.RED) );
        content.add( new ExpandingPanel("Blue", Color.BLUE) );
        content.add( new ExpandingPanel("Green", Color.GREEN) );

        JFrame frame = new JFrame("Expanding Panel");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( content);
        frame.setLocationByPlatform( true );
        frame.setSize(200, 300);
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
    }
}

panel.getPreferredSize().height != panel.getHeight()panel.getPreferredSize().width != panel.getWidth()时,你可以告诉某事是“嘎吱嘎吱”的panel.getPreferredSize().height != panel.getHeight()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM