簡體   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