Как реализовать JPanel, который показывает/скрывает контент в зависимости от его ширины?

Я пытаюсь реализовать JPanel, который отображает больше или меньше информации в зависимости от доступного размера.

По сути, идея состоит в том, чтобы иметь содержимое по умолчанию, подобное этому:

введите здесь описание изображения

Это может сжиматься до этого, когда пространство уменьшается:

введите здесь описание изображения

Мой код такой:

import net.miginfocom.swing.MigLayout;
import javax.swing.*;

class PanelDemo extends JPanel {
private final JLabel title = new JLabel();

private final JLabel counter1 = new JLabel("00");
private final JLabel counter1Label = new JLabel();

private final JLabel counter2 = new JLabel("00");
private final JLabel counter2Label = new JLabel();

/**
 * Instantiates a new obs app cadre message bloc panel.
 */
public PanelDemo() {
    this.setOpaque(false);
    initGUI();
}

private final void initGUI() {
    // 1°)
    final MigLayout migLayout = new MigLayout(
            "fillx, hidemode 2, debug",
            "[growprio 0][]" //define 4 columns
    );

    setLayout(migLayout);

    // 2°)
    //
    add(title, "spanx");
    add(counter1, "newline");
    add(counter1Label);
    add(counter2);
    add(counter2Label);
}

public static void main(String[] args) {
    final JFrame jFrame = new JFrame("test 4");
    jFrame.getContentPane().setLayout(new MigLayout("fillx, debug"));
    final PanelDemo item1 = new PanelDemo();
    item1.title.setText("Element 1");
    item1.counter1Label.setText("First lbl");
    item1.counter2Label.setText("Second lbl");
    jFrame.getContentPane().add(item1, "growx, gpx 110");


    final PanelDemo item2 = new PanelDemo();
    item2.title.setText("Element 2");
    item2.counter1Label.setText("First lbl");
    item2.counter2Label.setText("Second lbl");
    jFrame.getContentPane().add(item2, "growx, gpx 100");

    jFrame.pack();
    jFrame.setVisible(true);
} }

Я попытался добавить ComponentListener и переопределить componentResized(), чтобы найти, когда я могу показать/скрыть свои вторичные метки, но мне это не удалось.

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

Update1: я подумал... что, если установить минимальную ширину на counter1+label1, а максимальный размер на counter2+label2, а затем прослушать операции изменения размера и изменить предпочтительный размер либо на его минимальный или его максимум. Сработает ли этот механизм?


person Pigelvy    schedule 26.03.2013    source источник


Ответы (2)


Как насчет этого:

public static JPanel panel(String name) {
    JPanel panel = new JPanel(new MigLayout("insets 0, wrap 4, fillx, debug", "[][][shrink 200][shrink 200, grow 200]"));
    panel.add(new JLabel(name), "spanx 4");
    panel.add(new JLabel("00"));
    panel.add(new JLabel("First lbl"));
    panel.add(new JLabel("01"));
    panel.add(new JLabel("Second lbl"));
    return panel;
}

public static void main(String[] args) {
    JPanel panel = new JPanel(new MigLayout("insets 10, gap 10, fillx, debug"));
    panel.add(panel("Element 1"), "w (50% - 15)!");
    panel.add(panel("Element 2"), "w (50% - 15)!");

    JFrame frame = new JFrame();
    frame.setContentPane(panel);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
}

У меня возникли проблемы с одинаковым изменением размера двух основных столбцов; Мне пришлось сделать это, установив ширину компонентов, а не столбцов. Я не уверен, почему это так.

person Russell Zahniser    schedule 26.03.2013
comment
Поведение не совсем ожидаемое. Я должен был быть яснее. Когда пространство, доступное для вторых меток (2-й счетчик + 2-е описание), больше не доступно, я хочу, чтобы весь компонент изменил свое состояние, удалив/установивVisible(false) вторичные метки и уменьшив его предпочтительный размер, чтобы отразить новый макет . Позже, когда в родительском контейнере будет больше свободного места, моя панель должна вернуться в исходное полное состояние. Имеет ли смысл моя идея? - person Pigelvy; 27.03.2013

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

Вот пример:

MigLayout layout = new MigLayout("fill");
JPanel panel = new JPanel(layout);

JLabel label1 = new JLabel("Label 1");
label1.putClientProperty("autohide.width", 300);

JLabel label2 = new JLabel("Label 2");
label2.putClientProperty("autohide.width", 200);

panel.add(label1, "grow");
panel.add(label2, "grow");                

layout.addLayoutCallback(new LayoutCallback() {
    @Override
    public void correctBounds(ComponentWrapper wrapper) {
        JComponent component = (JComponent) wrapper.getComponent();

        Number width = (Number) component.getClientProperty("autohide.width");
        if (width != null) {
            if (component.isVisible() && wrapper.getParent().getWidth() < width.intValue()) {
                component.setVisible(false);
            } else if (!component.isVisible() && wrapper.getParent().getWidth() > width.intValue()) {
                component.setVisible(true);
            }
        }
    }
});

Здесь метка1 скрывается, когда ширина панели становится меньше 300 пикселей, а метка2 исчезает, когда ширина становится меньше 200 пикселей.

person Emmanuel Bourg    schedule 02.11.2016