具有可扩展单元的动态布局

发布于 2024-11-30 01:28:54 字数 1082 浏览 1 评论 0原文

我真的被必须用 java swing 制作的布局所困扰。

我必须构建一个动态表单,同时迭代标签和输入组件的向量。

它应该是这样的:

在此处输入图像描述

在此图像中,您可以看到结果应该是什么。绿线之间是一对标签/输入组件。我还得到一个约束,告诉我是否必须将它们布置在一行 50/50 或两行或一行 25/75 或 75/25 中。此外,整个表格的大小必须调整,且 50/50、25/75 和 75/25 比例仍然正确。

我尝试了 GridBagLayout,它工作得很好,但正如您在图片的第一行中看到的,标签可能很长。所以我使用了 JTextarea 但 GridBagLayout 将其切断。我也尝试过 JGoodies FormLayout,但在使用长标签的 Textarea 时也遇到了麻烦。

25/75和75/25的比例并不是那么重要,但实际上这也是我必须要做的一部分。

我认为让 Textarea 扩展其父组件真的很困难。

我还读/写了这些文章:

但是我还是被困住了。

你们中有人知道如何实现这一目标吗?

谢谢

I'm really stuck with a layout I have to make with java swing.

I have to build a dynamic form, while iterating through a vector of labels and input components.

Here is how it should:

enter image description here

In this image, you can see, what should be the result. Between the green lines is one pair of label/input component. I also get a constraint, telling me, if I have to lay them out in one row 50/50 or in two rows or in one row 25/75 or 75/25. Also the whole form must be resizable with the 50/50, 25/75 and 75/25 ratio still correct.

I tried GridBagLayout which worked quite nice, but as you can see in the first row in the picture, the label can be very long. So I used a JTextarea but GridBagLayout cut it off. I also treid JGoodies FormLayout, but also had trouble with the Textarea for long labels.

The 25/75 and 75/25 ratio is not that important, but actually it is also part of what I have to do.

I think it is just really difficult to make a Textarea expand its parent component.

I also read/wrote these aricles:

but I'm still stuck.

Does any one of you has any idea on how to accomplish this?

Thanks

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

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

发布评论

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

评论(2

温柔女人霸气范 2024-12-07 01:28:54

我已经有一段时间没有做很多 Swing 工作了,但有两个想法:

  1. 如果一个控件被切断,听起来好像你没有设置最小尺寸。

  2. 我认为任何现成的布局管理器都没有能够保持像 25/75 分割这样的尺寸比例的功能。但不要绝望!您可以编写自己的布局管理器。当我做很多 Swinging 的时候,我写了几个布局管理器。 (我会说,“针对特殊要求”,但实际上它们是针对相当一般的要求,而且让我感到惊讶的是,Java 没有包含预装布局管理器来处理此类事情。例如:您经常需要一行或一列按钮所有按钮的大小都相同,因此您必须找到哪个按钮具有最长的文本,然后调整所有其他按钮的大小以匹配它或者:设置行和列,其中每列的大小都调整为该列中最宽的东西。 ,但一列的宽度对其他列没有影响列;然后行也类似。)无论如何,您所描述的内容相当不寻常,因此您可能只想编写自己的布局管理器。

编写布局管理器的技巧就是实现几个关键功能: (a) 计算 X 和 Y 坐标,在给定总体大小的情况下放置每个控件; (b) 计算所需的最小尺寸; (c) 计算首选尺寸; (d) 计算您将使用的最大尺寸。嗯,可能还有一两个我忘记了,但这没什么大不了的。当我第一次想到“编写我自己的布局管理器”时,对我来说听起来像是“编写您自己的数据库引擎”或“编写您自己的编译器”,但实际上并没有那么可怕。通常只有几百行代码。

当然,如果这里的其他人可以告诉您如何使用其中一个预装布局管理器来做您想做的事情,那肯定要容易得多。

It's been a while since I've done much Swing, but two thoughts:

  1. If a control is being cut off, that sounds like you're not setting the minimum size.

  2. I don't think any of the off-the-shelf layout managers have a feature to maintain a ratio of sizes like your 25/75 split. But don't despair! You can write your own layout manager. Back when I was doing a lot of Swinging I wrote several layout manager. (I would say, "for specialized requirements", but really they were for quite general requirements, and it always surprised me that Java didn't include canned layout managers to handle such things. Like: you often want a row or column of buttons where all the buttons are the same size, so you have to find what button has the longest text, and then resize all the others to match it. Or: set up rows and columns where each colum is sized to the widest thing in that column, but the width of one column has no effect on other columns; then similarly for rows.) Anyway, what you're describing IS fairly unusual, so you may just want to write your own layout manager.

The trick to writing a layout manager is just to implement a few key functions: (a) Calculate the X and Y co-ordinates where you'll place each control given the overall size; (b) Calculate the minimum size required; (c) Calculate the preferred size; (d) Calculate the maximum size you'll use. Umm, there may be one or two more I'm forgetting, but it's not that big a deal. When I first thought about "writing my own layout manager" that sounded to me like "write your own database engine" or "write your own compiler" at first, but it's not really anywhere near that scary. It's typically a few hundred lines of code.

Of course if someone else on here can tell you how to do what you want to do with one of the canned layout managers, that's surely a lot easier.

好菇凉咱不稀罕他 2024-12-07 01:28:54

这是我到目前为止所得到的。此示例仅使用 JTextArea,但它也适用于其他组件(如我的图片所示)。目前它唯一不能做的就是像上图中的第 3 行那样布局组件(一个在另一个之上),但这应该没问题。

也许这可以帮助某人了解如何编写自定义布局管理器。

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

public class SwingApp extends JFrame {

    private static final long serialVersionUID = 1L;

    public static void main(final String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                final SwingApp app = new SwingApp();
            }
        });
    }

    private SwingApp() {
        setTitle(":)");
        setSize(800, 450);
        setResizable(true);
        setVisible(true);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        /*JTextArea textArea = new JTextArea("111111alks jdfksajfjsaölk jfölksajfölkjsa 
        lkfj salkjflkdsjf ölsajfölksaj fölkjs flkjdsa flkjsaölkfjsölk");*/
        //textArea.setLineWrap(true);
        //this.getContentPane().add(textArea);
        this.getContentPane().setLayout(new MyListLayoutManager());
        add(20, "left ajdskfj lksajdf dsafj lkdsjflksjalkfjsalk jlksjaf salkjfjdsflkjdslkfjlks "
                + "flk salkfjdslkfjlkds flkjds lkfjdslkfjlkds flkjds fljlfd left", "right dksjf "
                + "asjfjsa jfsjföldsajföljsa ölkfjdsaölk jf0932875 0983 09584093859438 095843 "
                + "5lkjf lksa jf lkdsajf 923879 825094lkjtwj lkdsf27509425 right");
        add(50, "left ajdskfj lksajdf dsafj lkdsjflksjalkfjsalk jlksjaf salkjfjdsflkjdslkfjlks "
                + "flk salkfjdslkfjlkds flkjds lkfjdslkfjlkds flkjds fljlfd left", "right dksjf "
                + "asjfjsa jfsjföldsajföljsa ölkfjdsaölk jf0932875 0983 09584093859438 095843 "
                + "5lkjf lksa jf lkdsajf 923879 825094lkjtwj lkdsf27509425 right");
        add(70, "left ajdskfj lksajdf dsafj lkdsjflksjalkfjsalk jlksjaf salkjfjdsflkjdslkfjlks "
                + "flk salkfjdslkfjlkds flkjds lkfjdslkfjlkds flkjds fljlfd left", "right dksjf "
                + "asjfjsa jfsjföldsajföljsa ölkfjdsaölk jf0932875 0983 09584093859438 095843 "
                + "5lkjf lksa jf lkdsajf 923879 825094lkjtwj lkdsf27509425 right");
        add(70, "left ajdskfj lksajdf dsafj lkdsjflksjalkfjsalk jlksjaf salkjfjdsflkjdslkfjlks "
                + "flk salkfjdslkfjlkds flkjds lkfjdslkfjlkds flkjds fljlfd left", "right dksjf "
                + "asjfjsa jfsjföldsajföljsa ölkfjdsaölk jf0932875 0983 09584093859438 095843 "
                + "5lkjf lksa jf lkdsajf 923879 825094lkjtwj lkdsf27509425 right");
        add(70, "left ajdskfj lksajdf dsafj lkdsjflksjalkfjsalk jlksjaf salkjfjdsflkjdslkfjlks "
                + "flk salkfjdslkfjlkds flkjds lkfjdslkfjlkds flkjds fljlfd left", "right dksjf "
                + "asjfjsa jfsjföldsajföljsa ölkfjdsaölk jf0932875 0983 09584093859438 095843 "
                + "5lkjf lksa jf lkdsajf 923879 825094lkjtwj lkdsf27509425 right");
    }

    private void add(final int leftPercent, final String leftText, final String rightText) {
        final JPanel panel = new JPanel(new MyRowLayoutManager(leftPercent));
        final JTextArea left = new JTextArea(leftText);
        left.setLineWrap(true);
        final JTextArea right = new JTextArea(rightText);
        right.setLineWrap(true);
        panel.add(left);
        panel.add(right);
        this.getContentPane().add(panel);
    }

    private class MyListLayoutManager implements LayoutManager {

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

        @Override
        public void removeLayoutComponent(final Component comp) {
        }

        @Override
        public Dimension preferredLayoutSize(final Container parent) {
            return new Dimension(600, 300);
        }

        @Override
        public Dimension minimumLayoutSize(final Container parent) {
            return new Dimension(0, 0);
        }

        @Override
        public void layoutContainer(final Container parent) {
            final Dimension size = parent.getSize();
            final int left = 0;
            int top = 0;
            for (int i = 0; i < parent.getComponentCount(); ++i) {
                final Component component = parent.getComponent(i);
                component.setSize(size.width, 1);
                final Dimension preferredSize = component.getPreferredSize();
                component.setBounds(left, top, preferredSize.width, preferredSize.height);
                top += preferredSize.height;
            }
        }
    }

    private class MyRowLayoutManager implements LayoutManager {

        private final int _leftPercent;

        private MyRowLayoutManager(final int leftPercent) {
            _leftPercent = leftPercent;
        }

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

        @Override
        public void removeLayoutComponent(final Component comp) {
        }

        @Override
        public Dimension preferredLayoutSize(final Container parent) {
            return new Dimension(600, 300);
        }

        @Override
        public Dimension minimumLayoutSize(final Container parent) {
            return new Dimension(0, 0);
        }

        @Override
        public void layoutContainer(final Container parent) {
            if (parent.getComponentCount() != 2) {
                throw new RuntimeException("Supports for exact 2 components");
            }
            final Dimension size = getSize();
            final int widthForLeft = size.width * _leftPercent / 100;
            final int widthForRight = size.width - widthForLeft;
            final Component left = parent.getComponent(0); //left Component
            left.setSize(widthForLeft, 1);
            final Dimension leftDimension = left.getPreferredSize();
            left.setBounds(0, 0, widthForLeft, leftDimension.height);
            final Component right = parent.getComponent(1); //right Component
            right.setSize(widthForRight, 1);
            final Dimension rightDimension = right.getPreferredSize();
            right.setBounds(widthForLeft, 0, widthForRight, rightDimension.height);
            parent.setSize(size.width, Math.max(leftDimension.height, rightDimension.height));
            parent.setPreferredSize(new Dimension(size.width, Math.max(leftDimension.height, rightDimension.height)));
        }
    }
}

通过将 main 方法包装到 invokeLater() 中,可以看到:

在此处输入图像描述

SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            final SwingApp app = new SwingApp();
        }
    });

Here is what I got so far. This example only uses JTextArea, but it works with other components as well (like my picture shows). The only thing it can't do at the moment is layout the components like in row 3 in the picture above (one on top of the other), but this should be no problem.

Maybe this helps someone to find out, how to write a custom layout manager.

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

public class SwingApp extends JFrame {

    private static final long serialVersionUID = 1L;

    public static void main(final String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                final SwingApp app = new SwingApp();
            }
        });
    }

    private SwingApp() {
        setTitle(":)");
        setSize(800, 450);
        setResizable(true);
        setVisible(true);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        /*JTextArea textArea = new JTextArea("111111alks jdfksajfjsaölk jfölksajfölkjsa 
        lkfj salkjflkdsjf ölsajfölksaj fölkjs flkjdsa flkjsaölkfjsölk");*/
        //textArea.setLineWrap(true);
        //this.getContentPane().add(textArea);
        this.getContentPane().setLayout(new MyListLayoutManager());
        add(20, "left ajdskfj lksajdf dsafj lkdsjflksjalkfjsalk jlksjaf salkjfjdsflkjdslkfjlks "
                + "flk salkfjdslkfjlkds flkjds lkfjdslkfjlkds flkjds fljlfd left", "right dksjf "
                + "asjfjsa jfsjföldsajföljsa ölkfjdsaölk jf0932875 0983 09584093859438 095843 "
                + "5lkjf lksa jf lkdsajf 923879 825094lkjtwj lkdsf27509425 right");
        add(50, "left ajdskfj lksajdf dsafj lkdsjflksjalkfjsalk jlksjaf salkjfjdsflkjdslkfjlks "
                + "flk salkfjdslkfjlkds flkjds lkfjdslkfjlkds flkjds fljlfd left", "right dksjf "
                + "asjfjsa jfsjföldsajföljsa ölkfjdsaölk jf0932875 0983 09584093859438 095843 "
                + "5lkjf lksa jf lkdsajf 923879 825094lkjtwj lkdsf27509425 right");
        add(70, "left ajdskfj lksajdf dsafj lkdsjflksjalkfjsalk jlksjaf salkjfjdsflkjdslkfjlks "
                + "flk salkfjdslkfjlkds flkjds lkfjdslkfjlkds flkjds fljlfd left", "right dksjf "
                + "asjfjsa jfsjföldsajföljsa ölkfjdsaölk jf0932875 0983 09584093859438 095843 "
                + "5lkjf lksa jf lkdsajf 923879 825094lkjtwj lkdsf27509425 right");
        add(70, "left ajdskfj lksajdf dsafj lkdsjflksjalkfjsalk jlksjaf salkjfjdsflkjdslkfjlks "
                + "flk salkfjdslkfjlkds flkjds lkfjdslkfjlkds flkjds fljlfd left", "right dksjf "
                + "asjfjsa jfsjföldsajföljsa ölkfjdsaölk jf0932875 0983 09584093859438 095843 "
                + "5lkjf lksa jf lkdsajf 923879 825094lkjtwj lkdsf27509425 right");
        add(70, "left ajdskfj lksajdf dsafj lkdsjflksjalkfjsalk jlksjaf salkjfjdsflkjdslkfjlks "
                + "flk salkfjdslkfjlkds flkjds lkfjdslkfjlkds flkjds fljlfd left", "right dksjf "
                + "asjfjsa jfsjföldsajföljsa ölkfjdsaölk jf0932875 0983 09584093859438 095843 "
                + "5lkjf lksa jf lkdsajf 923879 825094lkjtwj lkdsf27509425 right");
    }

    private void add(final int leftPercent, final String leftText, final String rightText) {
        final JPanel panel = new JPanel(new MyRowLayoutManager(leftPercent));
        final JTextArea left = new JTextArea(leftText);
        left.setLineWrap(true);
        final JTextArea right = new JTextArea(rightText);
        right.setLineWrap(true);
        panel.add(left);
        panel.add(right);
        this.getContentPane().add(panel);
    }

    private class MyListLayoutManager implements LayoutManager {

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

        @Override
        public void removeLayoutComponent(final Component comp) {
        }

        @Override
        public Dimension preferredLayoutSize(final Container parent) {
            return new Dimension(600, 300);
        }

        @Override
        public Dimension minimumLayoutSize(final Container parent) {
            return new Dimension(0, 0);
        }

        @Override
        public void layoutContainer(final Container parent) {
            final Dimension size = parent.getSize();
            final int left = 0;
            int top = 0;
            for (int i = 0; i < parent.getComponentCount(); ++i) {
                final Component component = parent.getComponent(i);
                component.setSize(size.width, 1);
                final Dimension preferredSize = component.getPreferredSize();
                component.setBounds(left, top, preferredSize.width, preferredSize.height);
                top += preferredSize.height;
            }
        }
    }

    private class MyRowLayoutManager implements LayoutManager {

        private final int _leftPercent;

        private MyRowLayoutManager(final int leftPercent) {
            _leftPercent = leftPercent;
        }

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

        @Override
        public void removeLayoutComponent(final Component comp) {
        }

        @Override
        public Dimension preferredLayoutSize(final Container parent) {
            return new Dimension(600, 300);
        }

        @Override
        public Dimension minimumLayoutSize(final Container parent) {
            return new Dimension(0, 0);
        }

        @Override
        public void layoutContainer(final Container parent) {
            if (parent.getComponentCount() != 2) {
                throw new RuntimeException("Supports for exact 2 components");
            }
            final Dimension size = getSize();
            final int widthForLeft = size.width * _leftPercent / 100;
            final int widthForRight = size.width - widthForLeft;
            final Component left = parent.getComponent(0); //left Component
            left.setSize(widthForLeft, 1);
            final Dimension leftDimension = left.getPreferredSize();
            left.setBounds(0, 0, widthForLeft, leftDimension.height);
            final Component right = parent.getComponent(1); //right Component
            right.setSize(widthForRight, 1);
            final Dimension rightDimension = right.getPreferredSize();
            right.setBounds(widthForLeft, 0, widthForRight, rightDimension.height);
            parent.setSize(size.width, Math.max(leftDimension.height, rightDimension.height));
            parent.setPreferredSize(new Dimension(size.width, Math.max(leftDimension.height, rightDimension.height)));
        }
    }
}

by wrapping main method into invokeLater() is possible to see :

enter image description here

SwingUtilities.invokeLater(new Runnable() {

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