JAVA Складная вертикальная раскладка - PullRequest
0 голосов
/ 15 сентября 2018

У меня есть 3 JPanels (давайте назовем каждый из них "BLOCK") в другом JPanel (назовем его "CENTER_DECORS") внутри JScollPane, который находится на одной из вкладок JTabbedPane.

Сейчас: когда я динамическиизменить высоту любого из этих BLOCK-ов («сложить» их, установив их высоту от 150 до 20). Я хочу, чтобы другие BLOCK-ы соответствующим образом обновляли свое вертикальное положение, чтобы они по-прежнему накладывались друг на друга, но степерь у меня есть «дыра» между БЛОКОМ с измененной (пониженной) высотой и следующей.

Я использую BoxLayout для CENTER_DECORS JPanel:

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

После того, как я изменил высотуБЛОК ...

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

... Я сразу звоню этот код:

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

Как ни странно, ничего не происходит вообще, даже высота не меняется, но когда я ухожупросто:

CENTER_DECORS.repaint();

... тогда, по крайней мере, изменит высоту, но не будет суммирования друг с другом.

ОБНОВЛЕНИЕ: решение должно иметьвозможность хранения сложенного / развернутого состояния с каждой строкойпоэтому, когда программа запускается, она может перейти в соответствующее состояние (свернуто / развернуто).

Кто-нибудь знает решение, чтобы эти BLOCK-ы по-прежнему придерживались друг друга вертикально, когда их высота изменяется?

РЕДАКТИРОВАТЬ: только после того, как я полностью проверил решение @MadProgrammer, я понял, что дублированный ответ не является правильным, поскольку он позволяет только развернуть / открыть 1 «блок» одновременно, и мне это нужноможет быть расширено независимо от того, сколько «блоков» + его код начинается со всего сложенного / свернутого, и мне нужно, чтобы он был в их нормальном состоянии, то есть - в большинстве случаев - в расширенном состоянии + мое решение не требует специального слушателябыть использованным (кроме MouseListener для состояний кнопок, что, конечно, нормально), таким образом, меньше кода.

Итак, после того, как весь день возился, я наконец-то создал свою собственную версию, вдохновленную подходом @ MadProgrammer - мой код теперь ведет себя точноЯ хотел (потому что я искал это решение, потому что мое приложение может иметь как десяткиразличные «блоки» в JPanel, с которыми довольно сложно справиться, поскольку они занимают слишком много места, которое может быть в большинстве случаев не нужно, поэтому было бы неплохо иметь возможность сложить их), поэтому приведенный ниже код на самом делеправильное решение, пожалуйста, удалите эту «дублирующую» вещь, поскольку она более не точна (см. мой отдельный ответ ниже).

Ответы [ 2 ]

0 голосов
/ 18 сентября 2018

Это именно то, что я хотел - это точное решение моего вопроса / проблемы (ПОМНИТЕ: это всего лишь небольшая часть, полученная из моего полного кода, где опущены миллионы других вещей, так что это может кажется, что там происходит много ненужных вещей, НО у этого есть причина для меня, чтобы иметь его там, и я бы не стал создавать пример "просто так" с нуля - если есть что-то, что вы находите ненужным, просто игнорируйте это или, если вы не можете это терпеть, просто удалите его, я не смогу пойти по этому пути, поскольку мне потребовалось бы полностью переписать то, что я использую в моем реальном коде, с квантовыми другими отдельными классами, чтобы, таким образом, он потерял свою функциональность (сломал мой код в моей программе), однажды введенный обратно в мой оригинальный огромный программный код - проще говоря: все, что вы видите в демоверсии, должно быть таким, каким оно может быть, для вас это может показаться ненужным. *

Чтобы проверить мой код (я использую NetBeans 8.0.2):

  • начать новый проект NetBeans
  • создать новый класс с именем "foldcomponentsdemo"
  • скопируйте код ниже
  • вставь туда
  • запустить (скомпилировать) его

Я здесь не для того, чтобы порадовать некоторых программистов, я публикую рабочее решение вопроса, который я задал.

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();
    }
}
0 голосов
/ 18 сентября 2018

Вот пример подхода, который позволит вам одновременно развернуть несколько панелей.

Решение содержит «ExpandingPanel», которая по существу состоит из двух компонентов:

  1. в BorderLayout.PAGE_START кнопка, при нажатии на которую можно развернуть / свернуть панель
  2. В BorderLayout.CENTER компонент, который будет переключаться на видимый / невидимый

Панели расширения добавляются вродительский контейнер, использующий вертикальный BoxLayout, так что вертикальный размер изменяется при переключении состояния каждой 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();
            }
        });
    }
}
...