JAVA可折叠垂直布局

问题描述 投票:0回答:2

我在JScollPane中的另一个JPanel(让我们将它命名为“BLOCK”)中有3个JPanels(让我们将它们命名为“BLOCK”),它位于JTabbedPane的一个选项卡中。

现在:当我动态地改变任何BLOCK-s的高度(通过将它们的高度从150设置为20来“折叠”它们)时,我希望其他BLOCK-s相应地更新它们的垂直位置,这样它们仍会堆叠在每个BLOCK上另外,但截至目前,我在BLOCK与高度(下降)和下一个高度之间有“洞”。

我正在使用BoxLayout作为CENTER_DECORS JPanel:

CENTER_DECORS.setLayout(new BoxLayout(CENTER_DECORS, BoxLayout.Y_AXIS));

在我改变BLOCK的高度之后......

BLOCK.setSize(BLOCK.getWidth(), 20);

...我立即打电话给这段代码:

CENTER_DECORS.repaint();
CENTER_DECORS.validate();
CENTER_DECORS.revalidate();

奇怪的是,根本没有任何事情发生,甚至高度都没有改变,但是当我离开时:

CENTER_DECORS.repaint();

...然后它至少改变高度,但不会发生彼此堆叠。

更新:解决方案必须有选项来存储每行的折叠/展开状态,因此当程序启动时,它可以gp到适当的状态(折叠/展开)。

有没有人知道一个解决方案,以便那些BLOCK-s在高度变化时仍会垂直相互粘连?

编辑:只有在我完全测试了@MadProgrammer解决方案之后,才意识到重复的答案不正确,因为它只允许一次扩展/打开1个“块”,无论有多少块,我都需要它自由扩展“+他的代码以折叠/折叠的所有内容开始,我需要它处于正常状态 - 大部分时间 - 扩展状态+我的解决方案不需要使用任何特殊的侦听器(除了MouseListener,用于按钮状态,这是当然是正常的,因此编码较少。

所以,在整天摆弄之后,我终于根据@MadProgrammer的方法制作了我自己的版本 - 我的代码现在表现得非常符合我想要的(我之所以正在寻找这个解决方案的原因是我的应用程序可能有几十个不同的“块”在一个JPanel很难管理,因为它们占用太多空间,可能大部分时间都不需要,所以选择折叠它们是非常好的选择),所以下面的代码实际上是正确的解决方案,请删除那个“复制”的东西,因为它不再准确(见下面的单独答案)。

java swing layout jpanel layout-manager
2个回答
0
投票

下面是一个允许您一次扩展多个面板的方法示例。

该解决方案包含一个“ExpandingPanel”,它基本上有两个组件:

  1. 在BorderLayout.PAGE_START中,单击一个按钮将展开/折叠面板
  2. 在BorderLayout.CENTER中将切换可见/不可见的组件

使用垂直BoxLayout将ExpandingPanel添加到父容器中,因此垂直大小会随着每个ExpandingPanel的状态切换而更改。

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

public class ExpandingPanel2 extends JPanel
{
    private JPanel expanding;

    public ExpandingPanel2(String text, Component expanding)
    {
        setLayout( new BorderLayout() );

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

        expanding.setVisible(false);
        add(expanding, BorderLayout.CENTER);

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

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

    @Override
    public Dimension getMaximumSize()
    {
        Dimension size = getPreferredSize();
        size.width = Integer.MAX_VALUE;

        return size;
    }

    private static void createAndShowGUI()
    {
        Box content = Box.createVerticalBox();

        content.add( createExpandingPanel("Red", Color.RED, 50));
        content.add( createExpandingPanel("Blue", Color.BLUE, 100));
        content.add( createExpandingPanel("Green", Color.GREEN, 200));

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

    private static ExpandingPanel2 createExpandingPanel(String text, Color background, int size)
    {
        JPanel content = new JPanel();
        content.setBackground(background);
        content.setPreferredSize(new Dimension(100, size));

        return new ExpandingPanel2(text, content);
    }


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

0
投票

这正是我想要的 - 这是我的问题/问题的确切解决方案(记住:这只是我的完整代码中的一小部分衍生物,其中省略了数以万计的其他东西,所以看起来似乎有很多不必要的东西继续那里,但它有理由让我在那里,我不会从头开始创建示例“就像那样” - 如果有任何你认为不必要的东西只是忽略它或如果你不能忍受它只是删除它,我不能这样,因为它需要我完全重写我在实际代码中使用的量子其他单独的类,因此它会失去其功能(在我的程序中打破我的代码)一旦被引入回到我原来庞大的程序代码 - 简单地说:你在演示中看到的所有东西都必须是你可能看起来不必要的东西+它对代码的功能没有任何影响!

要测试我的代码(我使用的是NetBeans 8.0.2):

  • 启动新的NetBeans项目
  • 创建名为“foldingcomponentsdemo”的新类
  • 复制下面的代码
  • 粘在那里
  • 运行(编译)它

我不是在这里取悦一些程序员的感受,我发布工作解决方案我问过的问题。

package foldingcomponentsdemo;

import static foldingcomponentsdemo.Constants.BLOCK_COLOR_BG;
import static foldingcomponentsdemo.Constants.BLOCK_H;
import static foldingcomponentsdemo.Constants.BLOCK_HEADER_BG_COLOR;
import static foldingcomponentsdemo.Constants.BLOCK_HEADER_BORDER_COLOR;
import static foldingcomponentsdemo.Constants.BLOCK_HEADER_FG_COLOR;
import static foldingcomponentsdemo.Constants.BLOCK_HEADER_H;
import static foldingcomponentsdemo.Constants.BLOCK_HEADER_LABEL_FG_COLOR;
import static foldingcomponentsdemo.Constants.BLOCK_HEADER_LABEL_FONT_SIZE;
import static foldingcomponentsdemo.Constants.BUTTON_FOLD_COLOR_BG;
import static foldingcomponentsdemo.Constants.BUTTON_FOLD_COLOR_BG_DOWN;
import static foldingcomponentsdemo.Constants.BUTTON_FOLD_COLOR_BG_OVER;
import static foldingcomponentsdemo.Constants.BUTTON_WH;
import static foldingcomponentsdemo.Constants.GAP;
import static foldingcomponentsdemo.Constants.INNER_W;
import static foldingcomponentsdemo.Constants.LABEL_TEXT;
import static foldingcomponentsdemo.Constants.MAINWINDOW_H;
import static foldingcomponentsdemo.Constants.MAINWINDOW_W;
import static foldingcomponentsdemo.Constants.MARGIN;
import static foldingcomponentsdemo.Constants.NUMBER_OF_BLOCKS;
import static foldingcomponentsdemo.FoldingComponentsDemo.getScene;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

class Constants {

    public static final int MARGIN = 2;
    public static final int BLOCK_H = 100;
    public static final int NUMBER_OF_BLOCKS = 5;
    public static final int SCROLLER_HOR_WIDTH = 26;
    public static final int MAINWINDOW_W = 300;
    public static final int MAINWINDOW_H = BLOCK_H * (NUMBER_OF_BLOCKS - 2);
    public static final int INNER_W = MAINWINDOW_W - SCROLLER_HOR_WIDTH;
    public static final int BLOCK_HEADER_H = 20;
    public static final int BUTTON_WH = BLOCK_HEADER_H - (MARGIN * 2);
    public static final int BLOCK_HEADER_LABEL_FONT_SIZE = 11;
    public static final Color BLOCK_HEADER_BG_COLOR = Color.decode("#000000");
    public static final Color BLOCK_HEADER_FG_COLOR = Color.decode("#cccccc");
    public static final Color BLOCK_HEADER_BORDER_COLOR = Color.decode("#777777");
    public static final Color BUTTON_FOLD_COLOR_BG = Color.decode("#ff0000");
    public static final Color BUTTON_FOLD_COLOR_BG_OVER = Color.decode("#999999");
    public static final Color BUTTON_FOLD_COLOR_BG_DOWN = Color.decode("#cccccc");
    public static final Color BLOCK_COLOR_BG = Color.decode("#555555");
    public static final Color BLOCK_HEADER_LABEL_FG_COLOR = Color.decode("#ffffff");
    public static final String GAP = " ";
    public static final String LABEL_TEXT = "click red button on right to (un)fold";

}

public class FoldingComponentsDemo {

    private static Block block;
    private static final FoldingContainer SCENE = new FoldingContainer();
    private static final JScrollPane SCROLLER = new JScrollPane(SCENE);

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            createGUI();
        });
    }

    private static void createGUI() {

        for (int i = 0; i < NUMBER_OF_BLOCKS; i++) {
            block = new Block("BLOCK_" + i, INNER_W, BLOCK_H);
            SCENE.add(block);
        }

        JFrame frame = new JFrame("Folding components");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(SCROLLER);
        frame.setSize(MAINWINDOW_W, MAINWINDOW_H);
        frame.setVisible(true);
    }

    public static FoldingContainer getScene() {
        return SCENE;
    }
}

class Block extends JPanel {

    private static Dimension BLOCK_SIZE;
    public boolean isFolded;

    public Block(String name, int innerW, int blockHeight) {

        this.isFolded = false;
        BLOCK_SIZE = new Dimension((int) innerW, blockHeight);

        setName(name);
        setLayout(null);
        setPreferredSize(BLOCK_SIZE);
        setMinimumSize(BLOCK_SIZE);
        setMaximumSize(BLOCK_SIZE);
        setBackground(BLOCK_COLOR_BG);
        setBorder(BorderFactory.createLineBorder(Color.black, 1, false));
        add(new Header());
    }
}

class Label extends JLabel {

    public Label(String text, int innerW) {

        setText(text);
        setSize(innerW, BLOCK_HEADER_H);
        setForeground(BLOCK_HEADER_LABEL_FG_COLOR);
        setFont(new Font("Tahoma", Font.PLAIN, BLOCK_HEADER_LABEL_FONT_SIZE));
    }
}

class Header extends JPanel {

    public Header() {
        setLayout(null);
        setSize(INNER_W, BLOCK_HEADER_H);
        setBackground(BLOCK_HEADER_BG_COLOR);
        setForeground(BLOCK_HEADER_FG_COLOR);
        setBorder(BorderFactory.createLineBorder(BLOCK_HEADER_BORDER_COLOR, 1, false));

        add(new Label(GAP + LABEL_TEXT, INNER_W));

        JButton BUTTON_FOLD = new JButton();
        BUTTON_FOLD.setBounds(INNER_W - (BUTTON_WH * 2), MARGIN, BUTTON_WH, BUTTON_WH);
        BUTTON_FOLD.setMargin(new Insets(0, 0, 0, 0));
        BUTTON_FOLD.setFocusPainted(false);
        BUTTON_FOLD.setBackground(BUTTON_FOLD_COLOR_BG);
        BUTTON_FOLD.setCursor(new Cursor(Cursor.HAND_CURSOR));
        BUTTON_FOLD.addMouseListener(new MouseAdapter() {
            public void mouseEntered(MouseEvent e) {
                BUTTON_FOLD.setBackground(BUTTON_FOLD_COLOR_BG_OVER);
            }

            public void mouseExited(MouseEvent e) {
                BUTTON_FOLD.setBackground(BUTTON_FOLD_COLOR_BG);
            }

            public void mousePressed(MouseEvent e) {
                BUTTON_FOLD.setBackground(BUTTON_FOLD_COLOR_BG_DOWN);
            }

            public void mouseClicked(MouseEvent e) {
                BUTTON_FOLD.setBackground(BUTTON_FOLD_COLOR_BG_DOWN);
                Block blck = (Block) BUTTON_FOLD.getParent().getParent();
                blck.isFolded = !blck.isFolded;
                ((FoldingLayout) getScene().getLayout()).setExpanded(blck);
            }
        });

        add(BUTTON_FOLD);
    }
}

class FoldingContainer extends JPanel {

    FoldingLayout layout;

    public FoldingContainer() {
        setName("Folding container");
        layout = new FoldingLayout();
        setLayout(layout);
    }
}

class FoldingLayout implements LayoutManager {

    private Component block;
    private String initialised;

    public void setExpanded(Component BLOCK) {
        this.block = BLOCK;
        this.initialised = "yes";
        layoutContainer(block.getParent());
    }

    public Component getExpanded() {
        return block;
    }

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

    @Override
    public void removeLayoutComponent(Component comp) {
    }

    @Override
    public Dimension preferredLayoutSize(Container cont) {
        return minimumLayoutSize(cont);
    }

    @Override
    public Dimension minimumLayoutSize(Container cont) {
        int width = INNER_W;
        int height = 0;
        for (Component comp : cont.getComponents()) {
            height += comp.getHeight();
        }
        return new Dimension(width, height);
    }

    @Override
    public void layoutContainer(Container cont) {
        Insets insets = cont.getInsets();
        int x = insets.left;
        int y = insets.top;

        for (Component comp : cont.getComponents()) {
            if (initialised == null) {
                comp.setSize(comp.getMinimumSize().width, comp.getMinimumSize().height);
            } else {
                if (((Block) comp).isFolded) {
                    comp.setSize(comp.getMinimumSize().width, BLOCK_HEADER_H);
                } else {
                    comp.setSize(comp.getMinimumSize().width, comp.getMinimumSize().height);
                }
            }
            comp.setLocation(x, y);
            y += comp.getHeight();
        }

        // update for scroller
        cont.getParent().revalidate();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.