如何防止Boxlayout/Box拉伸子组件?

发布于 2024-12-16 15:38:53 字数 3294 浏览 5 评论 0 原文

正如您在下面的可运行代码中看到的,我尝试拥有一个带有可扩展子框的框。孩子们的盒子可以改变它们的大小,这一切都很好。主要问题是大小始终相对于父级。但我希望它们有一个特定的大小,以防万一没有地方再使用 JScrollPane。目前他们只缩小其他子盒子。

我尝试了胶水和填充剂,但没有用。胶水没有任何作用,而填充物有副作用,总是保持在某个位置(即使 ScrollPane 正在运行)。有这么多可用空间真是太难看了。

那么,你知道有什么好方法可以防止盒子拉伤孩子吗?

先感谢您!

import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.border.TitledBorder;


public class ExpandableMenueDemo {
    Box allBoxes; 
    ExpandableMenueDemo(){
        allBoxes = Box.createVerticalBox();

        TitledBorder title;
        title = BorderFactory.createTitledBorder("Filter");
        allBoxes.setBorder(title);

        for (int i = 0 ;i<3;i++){
            //generate collapsable components
            SubBox b = new SubBox("SubBox"+i);
            allBoxes.add(b.getSwingBox());

        }
        allBoxes.add(Box.createVerticalGlue());
    }

    public Container getMenue(){
        return allBoxes;
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        ExpandableMenueDemo m = new ExpandableMenueDemo();
        Box mainBox = Box.createHorizontalBox();

        mainBox.add(new JScrollPane(m.getMenue()));
        mainBox.add(new JTable(20,5));

        frame.setContentPane(mainBox);
        frame.pack();
        frame.setVisible(true);
    }


    class SubBox{
        Box box;
        Box header; 
        String name; 
        JButton cBtn;
        boolean isCollapsed = true;
        JLabel headerLine; 

        SubBox(String name) {
            this.name= name;
            box = Box.createVerticalBox();

            headerLine = new JLabel(name+" () :");

            header= Box.createHorizontalBox();
            cBtn = new JButton("v");
            cBtn.addActionListener(new ActionListener(){

                @Override
                public void actionPerformed(ActionEvent arg0) {
                    if (isCollapsed)show();
                    else collapse();
                }
            });
            collapse();

            header.add(cBtn);
            header.add(Box.createHorizontalStrut(10));
            header.add(headerLine);
            header.add(Box.createHorizontalGlue());

        }

        Box getSwingBox() {
            Box b = Box.createVerticalBox();    
            b.add(header);
            b.add(box);
            return b;
        }

        public void collapse(){
            System.out.println("collapse");
            box.removeAll();
            this.isCollapsed=true;
            cBtn.setText("v");
        }

        public void show(){
            System.out.println("show");
            box.removeAll();
            this.isCollapsed=false;
            cBtn.setText("^");

            for (int i = 0; i<3;i++) { 
               Box b = Box.createHorizontalBox();
               b.add(Box.createHorizontalStrut(20));
               b.add(new JCheckBox("checkBox "+i));
               b.add(Box.createHorizontalGlue());
               box.add(b);
            }
        }
    }
}

As you can see in the runnable code below, i try to have a Box with expandable child-boxes. The children Boxes can change they size and this all works good. The main problem is that the size is always relative to the parent. But I want them to have a specific size and in case there is no place anymore use the JScrollPane. At the moment they shrink the other children-boxes only.

I tried Glue and Filler, but it didn't work. The glue just had no effect and the filler had the side effect to keep always some place at the (even when the ScrollPane is in action). That is pretty ugly to have there so much free space.

So, do you know a good way to prevent the Boxes from stretching the children?

Thank you in advance!

import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.border.TitledBorder;


public class ExpandableMenueDemo {
    Box allBoxes; 
    ExpandableMenueDemo(){
        allBoxes = Box.createVerticalBox();

        TitledBorder title;
        title = BorderFactory.createTitledBorder("Filter");
        allBoxes.setBorder(title);

        for (int i = 0 ;i<3;i++){
            //generate collapsable components
            SubBox b = new SubBox("SubBox"+i);
            allBoxes.add(b.getSwingBox());

        }
        allBoxes.add(Box.createVerticalGlue());
    }

    public Container getMenue(){
        return allBoxes;
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        ExpandableMenueDemo m = new ExpandableMenueDemo();
        Box mainBox = Box.createHorizontalBox();

        mainBox.add(new JScrollPane(m.getMenue()));
        mainBox.add(new JTable(20,5));

        frame.setContentPane(mainBox);
        frame.pack();
        frame.setVisible(true);
    }


    class SubBox{
        Box box;
        Box header; 
        String name; 
        JButton cBtn;
        boolean isCollapsed = true;
        JLabel headerLine; 

        SubBox(String name) {
            this.name= name;
            box = Box.createVerticalBox();

            headerLine = new JLabel(name+" () :");

            header= Box.createHorizontalBox();
            cBtn = new JButton("v");
            cBtn.addActionListener(new ActionListener(){

                @Override
                public void actionPerformed(ActionEvent arg0) {
                    if (isCollapsed)show();
                    else collapse();
                }
            });
            collapse();

            header.add(cBtn);
            header.add(Box.createHorizontalStrut(10));
            header.add(headerLine);
            header.add(Box.createHorizontalGlue());

        }

        Box getSwingBox() {
            Box b = Box.createVerticalBox();    
            b.add(header);
            b.add(box);
            return b;
        }

        public void collapse(){
            System.out.println("collapse");
            box.removeAll();
            this.isCollapsed=true;
            cBtn.setText("v");
        }

        public void show(){
            System.out.println("show");
            box.removeAll();
            this.isCollapsed=false;
            cBtn.setText("^");

            for (int i = 0; i<3;i++) { 
               Box b = Box.createHorizontalBox();
               b.add(Box.createHorizontalStrut(20));
               b.add(new JCheckBox("checkBox "+i));
               b.add(Box.createHorizontalGlue());
               box.add(b);
            }
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

乱世争霸 2024-12-23 15:38:53

BoxLayout 可以接受 setXxxSize

也许是展开/折叠JPanels 嵌套另一个 JComponent

在此输入图像描述

import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class ExpandingPanels extends MouseAdapter {

    private ActionPanel[] aps;
    private JPanel[] panels;

    public ExpandingPanels() {
        assembleActionPanels();
        assemblePanels();
    }

    @Override
    public void mousePressed(MouseEvent e) {
        ActionPanel ap = (ActionPanel) e.getSource();
        if (ap.target.contains(e.getPoint())) {
            ap.toggleSelection();
            togglePanelVisibility(ap);
        }
    }

    private void togglePanelVisibility(ActionPanel ap) {
        int index = getPanelIndex(ap);
        if (panels[index].isShowing()) {
            panels[index].setVisible(false);
        } else {
            panels[index].setVisible(true);
        }
        ap.getParent().validate();
    }

    private int getPanelIndex(ActionPanel ap) {
        for (int j = 0; j < aps.length; j++) {
            if (ap == aps[j]) {
                return j;
            }
        }
        return -1;
    }

    private void assembleActionPanels() {
        String[] ids = {"level 1", "level 2", "level 3", "level 4"};
        aps = new ActionPanel[ids.length];
        for (int j = 0; j < aps.length; j++) {
            aps[j] = new ActionPanel(ids[j], this);
        }
    }

    private void assemblePanels() {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(2, 1, 2, 1);
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        JPanel p1 = new JPanel(new GridBagLayout());
        gbc.gridwidth = GridBagConstraints.RELATIVE;
        p1.add(new JButton("button 1"), gbc);
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        p1.add(new JButton("button 2"), gbc);
        gbc.gridwidth = GridBagConstraints.RELATIVE;
        p1.add(new JButton("button 3"), gbc);
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        p1.add(new JButton("button 4"), gbc);
        JPanel p2 = new JPanel(new GridBagLayout());
        gbc.gridwidth = 1;
        gbc.anchor = GridBagConstraints.EAST;
        p2.add(new JLabel("enter"), gbc);
        gbc.anchor = GridBagConstraints.WEST;
        p2.add(new JTextField(8), gbc);
        gbc.anchor = GridBagConstraints.CENTER;
        p2.add(new JButton("button 1"), gbc);
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        p2.add(new JButton("button 2"), gbc);
        JPanel p3 = new JPanel(new BorderLayout());
        JTextArea textArea = new JTextArea(8, 12);
        textArea.setLineWrap(true);
        p3.add(new JScrollPane(textArea));
        JPanel p4 = new JPanel(new GridBagLayout());
        addComponents(new JLabel("label 1"), new JTextField(12), p4, gbc);
        addComponents(new JLabel("label 2"), new JTextField(16), p4, gbc);
        gbc.gridwidth = 2;
        gbc.gridy = 2;
        p4.add(new JSlider(), gbc);
        gbc.gridy++;
        JPanel p5 = new JPanel(new GridBagLayout());
        p5.add(new JButton("button 1"), gbc);
        p5.add(new JButton("button 2"), gbc);
        p5.add(new JButton("button 3"), gbc);
        p5.add(new JButton("button 4"), gbc);
        gbc.weighty = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        p4.add(p5, gbc);
        panels = new JPanel[]{p1, p2, p3, p4};
    }

    private void addComponents(Component c1, Component c2, Container c, GridBagConstraints gbc) {
        gbc.anchor = GridBagConstraints.EAST;
        gbc.gridwidth = GridBagConstraints.RELATIVE;
        c.add(c1, gbc);
        gbc.anchor = GridBagConstraints.WEST;
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        c.add(c2, gbc);
        gbc.anchor = GridBagConstraints.CENTER;
    }

    private JPanel getComponent() {
        JPanel panel = new JPanel(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(1, 3, 0, 3);
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        for (int j = 0; j < aps.length; j++) {
            panel.add(aps[j], gbc);
            panel.add(panels[j], gbc);
            panels[j].setVisible(false);
        }
        JLabel padding = new JLabel();
        gbc.weighty = 1.0;
        panel.add(padding, gbc);
        return panel;
    }

    public static void main(String[] args) {
        Runnable doRun = new Runnable() {

            @Override
            public void run() {
                ExpandingPanels test = new ExpandingPanels();
                JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.getContentPane().add(new JScrollPane(test.getComponent()));
                f.setSize(360, 500);
                f.setLocation(200, 100);
                f.setVisible(true);
            }
        };
        SwingUtilities.invokeLater(doRun);
    }
}

class ActionPanel extends JPanel {

    private static final long serialVersionUID = 1L;
    private String text;
    private Font font;
    private boolean selected;
    private BufferedImage open, closed;
    public Rectangle target;
    final int OFFSET = 30,
            PAD = 5;

    ActionPanel(String text, MouseListener ml) {
        this.text = text;
        addMouseListener(ml);
        font = new Font("sans-serif", Font.PLAIN, 12);
        selected = false;
        setBackground(new Color(200, 200, 220));
        setPreferredSize(new Dimension(200, 20));
        setBorder(BorderFactory.createRaisedBevelBorder());
        setPreferredSize(new Dimension(200, 20));
        createImages();
        setRequestFocusEnabled(true);
    }

    public void toggleSelection() {
        selected = !selected;
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        int w = getWidth();
        int h = getHeight();
        if (selected) {
            g2.drawImage(open, PAD, 0, this);
        } else {
            g2.drawImage(closed, PAD, 0, this);
        }
        g2.setFont(font);
        FontRenderContext frc = g2.getFontRenderContext();
        LineMetrics lm = font.getLineMetrics(text, frc);
        float height = lm.getAscent() + lm.getDescent();
        float x = OFFSET;
        float y = (h + height) / 2 - lm.getDescent();
        g2.drawString(text, x, y);
    }

    private void createImages() {
        int w = 20;
        int h = getPreferredSize().height;
        target = new Rectangle(2, 0, 20, 18);
        open = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = open.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setPaint(getBackground());
        g2.fillRect(0, 0, w, h);
        int[] x = {2, w / 2, 18};
        int[] y = {4, 15, 4};
        Polygon p = new Polygon(x, y, 3);
        g2.setPaint(Color.green.brighter());
        g2.fill(p);
        g2.setPaint(Color.blue.brighter());
        g2.draw(p);
        g2.dispose();
        closed = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        g2 = closed.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setPaint(getBackground());
        g2.fillRect(0, 0, w, h);
        x = new int[]{3, 13, 3};
        y = new int[]{4, h / 2, 16};
        p = new Polygon(x, y, 3);
        g2.setPaint(Color.red);
        g2.fill(p);
        g2.setPaint(Color.blue.brighter());
        g2.draw(p);
        g2.dispose();
    }
}

BoxLayout can accepting setXxxSize,

maybe better example for expanding/collapsing JPanels nests another JComponents

enter image description here

import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class ExpandingPanels extends MouseAdapter {

    private ActionPanel[] aps;
    private JPanel[] panels;

    public ExpandingPanels() {
        assembleActionPanels();
        assemblePanels();
    }

    @Override
    public void mousePressed(MouseEvent e) {
        ActionPanel ap = (ActionPanel) e.getSource();
        if (ap.target.contains(e.getPoint())) {
            ap.toggleSelection();
            togglePanelVisibility(ap);
        }
    }

    private void togglePanelVisibility(ActionPanel ap) {
        int index = getPanelIndex(ap);
        if (panels[index].isShowing()) {
            panels[index].setVisible(false);
        } else {
            panels[index].setVisible(true);
        }
        ap.getParent().validate();
    }

    private int getPanelIndex(ActionPanel ap) {
        for (int j = 0; j < aps.length; j++) {
            if (ap == aps[j]) {
                return j;
            }
        }
        return -1;
    }

    private void assembleActionPanels() {
        String[] ids = {"level 1", "level 2", "level 3", "level 4"};
        aps = new ActionPanel[ids.length];
        for (int j = 0; j < aps.length; j++) {
            aps[j] = new ActionPanel(ids[j], this);
        }
    }

    private void assemblePanels() {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(2, 1, 2, 1);
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        JPanel p1 = new JPanel(new GridBagLayout());
        gbc.gridwidth = GridBagConstraints.RELATIVE;
        p1.add(new JButton("button 1"), gbc);
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        p1.add(new JButton("button 2"), gbc);
        gbc.gridwidth = GridBagConstraints.RELATIVE;
        p1.add(new JButton("button 3"), gbc);
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        p1.add(new JButton("button 4"), gbc);
        JPanel p2 = new JPanel(new GridBagLayout());
        gbc.gridwidth = 1;
        gbc.anchor = GridBagConstraints.EAST;
        p2.add(new JLabel("enter"), gbc);
        gbc.anchor = GridBagConstraints.WEST;
        p2.add(new JTextField(8), gbc);
        gbc.anchor = GridBagConstraints.CENTER;
        p2.add(new JButton("button 1"), gbc);
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        p2.add(new JButton("button 2"), gbc);
        JPanel p3 = new JPanel(new BorderLayout());
        JTextArea textArea = new JTextArea(8, 12);
        textArea.setLineWrap(true);
        p3.add(new JScrollPane(textArea));
        JPanel p4 = new JPanel(new GridBagLayout());
        addComponents(new JLabel("label 1"), new JTextField(12), p4, gbc);
        addComponents(new JLabel("label 2"), new JTextField(16), p4, gbc);
        gbc.gridwidth = 2;
        gbc.gridy = 2;
        p4.add(new JSlider(), gbc);
        gbc.gridy++;
        JPanel p5 = new JPanel(new GridBagLayout());
        p5.add(new JButton("button 1"), gbc);
        p5.add(new JButton("button 2"), gbc);
        p5.add(new JButton("button 3"), gbc);
        p5.add(new JButton("button 4"), gbc);
        gbc.weighty = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        p4.add(p5, gbc);
        panels = new JPanel[]{p1, p2, p3, p4};
    }

    private void addComponents(Component c1, Component c2, Container c, GridBagConstraints gbc) {
        gbc.anchor = GridBagConstraints.EAST;
        gbc.gridwidth = GridBagConstraints.RELATIVE;
        c.add(c1, gbc);
        gbc.anchor = GridBagConstraints.WEST;
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        c.add(c2, gbc);
        gbc.anchor = GridBagConstraints.CENTER;
    }

    private JPanel getComponent() {
        JPanel panel = new JPanel(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(1, 3, 0, 3);
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        for (int j = 0; j < aps.length; j++) {
            panel.add(aps[j], gbc);
            panel.add(panels[j], gbc);
            panels[j].setVisible(false);
        }
        JLabel padding = new JLabel();
        gbc.weighty = 1.0;
        panel.add(padding, gbc);
        return panel;
    }

    public static void main(String[] args) {
        Runnable doRun = new Runnable() {

            @Override
            public void run() {
                ExpandingPanels test = new ExpandingPanels();
                JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.getContentPane().add(new JScrollPane(test.getComponent()));
                f.setSize(360, 500);
                f.setLocation(200, 100);
                f.setVisible(true);
            }
        };
        SwingUtilities.invokeLater(doRun);
    }
}

class ActionPanel extends JPanel {

    private static final long serialVersionUID = 1L;
    private String text;
    private Font font;
    private boolean selected;
    private BufferedImage open, closed;
    public Rectangle target;
    final int OFFSET = 30,
            PAD = 5;

    ActionPanel(String text, MouseListener ml) {
        this.text = text;
        addMouseListener(ml);
        font = new Font("sans-serif", Font.PLAIN, 12);
        selected = false;
        setBackground(new Color(200, 200, 220));
        setPreferredSize(new Dimension(200, 20));
        setBorder(BorderFactory.createRaisedBevelBorder());
        setPreferredSize(new Dimension(200, 20));
        createImages();
        setRequestFocusEnabled(true);
    }

    public void toggleSelection() {
        selected = !selected;
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        int w = getWidth();
        int h = getHeight();
        if (selected) {
            g2.drawImage(open, PAD, 0, this);
        } else {
            g2.drawImage(closed, PAD, 0, this);
        }
        g2.setFont(font);
        FontRenderContext frc = g2.getFontRenderContext();
        LineMetrics lm = font.getLineMetrics(text, frc);
        float height = lm.getAscent() + lm.getDescent();
        float x = OFFSET;
        float y = (h + height) / 2 - lm.getDescent();
        g2.drawString(text, x, y);
    }

    private void createImages() {
        int w = 20;
        int h = getPreferredSize().height;
        target = new Rectangle(2, 0, 20, 18);
        open = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = open.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setPaint(getBackground());
        g2.fillRect(0, 0, w, h);
        int[] x = {2, w / 2, 18};
        int[] y = {4, 15, 4};
        Polygon p = new Polygon(x, y, 3);
        g2.setPaint(Color.green.brighter());
        g2.fill(p);
        g2.setPaint(Color.blue.brighter());
        g2.draw(p);
        g2.dispose();
        closed = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        g2 = closed.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setPaint(getBackground());
        g2.fillRect(0, 0, w, h);
        x = new int[]{3, 13, 3};
        y = new int[]{4, h / 2, 16};
        p = new Polygon(x, y, 3);
        g2.setPaint(Color.red);
        g2.fill(p);
        g2.setPaint(Color.blue.brighter());
        g2.draw(p);
        g2.dispose();
    }
}
怀里藏娇 2024-12-23 15:38:53

您可以考虑使用 SwingX 中包含的 JXTaskPane/-Container,而不是重新发明轮子。它的 演示 在左侧显示了它的实际操作(作为任务窗格) - 这就是选择演示的部分。

Instead of re-inventing the wheel, you might consider to use JXTaskPane/-Container contained in SwingX. Its demo shows it in action (as taskPanes) at the left - that's the part for choosing the demos.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文