【问题标题】:How to implement a JPanel that shows/hide content depending on its width?如何实现根据宽度显示/隐藏内容的 JPanel?
【发布时间】:2023-03-27 14:43:01
【问题描述】:

我正在尝试实现一个 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,然后监听调整大小操作并将首选尺寸更改为无论是最小值还是最大值。这种机制会起作用吗?

【问题讨论】:

    标签: java swing layout miglayout


    【解决方案1】:

    这个怎么样:

    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);
    }
    

    我无法让两个主要列的大小相等;我必须通过在组件而不是列上设置宽度来做到这一点。我不知道为什么会这样。

    【讨论】:

    • 这种行为并不完全是预期的。我应该更清楚。当第二个标签(第二个计数器+第二个描述)的可用空间不再可用时,我希望整个组件通过删除/setVisible(false) 辅助标签来更改其状态并减小其首选大小以反映新布局.稍后,当父容器有更多可用空间时,我的面板应该返回到其初始满状态。我的想法有意义吗?
    【解决方案2】:

    我使用 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);
                }
            }
        }
    });
    

    这里label1在面板宽度缩小到300像素以下时隐藏,label2在宽度小于200像素时消失。

    【讨论】:

      猜你喜欢
      • 2011-01-15
      • 2014-09-18
      • 1970-01-01
      • 2013-01-04
      • 1970-01-01
      • 1970-01-01
      • 2011-08-18
      • 1970-01-01
      • 2015-10-26
      相关资源
      最近更新 更多