【问题标题】:How to optimize this kind of loop?如何优化这种循环?
【发布时间】:2014-09-07 12:46:45
【问题描述】:

我正在尝试制作这个 GUI。


我编写自己的布局,因为现有的布局管理器不符合我的要求 它有效,但我尝试通过使用循环来优化所有按钮的创建。

Test.class

public class Test {

    public static void main(String[] args) {
        JFrame f = new JFrame();
        JPanel parent = new JPanel();
        f.add(parent);
        parent.setLayout(new BoxLayout(parent, BoxLayout.X_AXIS));

        JPanel[] children = new JPanel[6];
        for (int i = 1; i < children.length; i++) {
            children[i] = new JPanel();
            children[i].setLayout(new XYLayout());
            children[i].setBorder(new LineBorder(Color.red));
            parent.add(children[i]);
        }

        int x = 0, y = 375, w = 0, h = 50;

        children[1].add(new JButton("8"), new XYConstraints(0, 25, 0, 50));
        children[1].add(new JButton("7"), new XYConstraints(0, 75, 0, 50));
        children[1].add(new JButton("6"), new XYConstraints(0, 125, 0, 50));
        children[1].add(new JButton("5"), new XYConstraints(0, 175, 0, 50));
        children[1].add(new JButton("4"), new XYConstraints(0, 225, 0, 50));
        children[1].add(new JButton("3"), new XYConstraints(0, 275, 0, 50));
        children[1].add(new JButton("2"), new XYConstraints(0, 325, 0, 50));
        children[1].add(new JButton("1"), new XYConstraints(0, 375, 0, 50));

        children[2].add(new JButton("7"), new XYConstraints(240, 25, 0, 100));
        children[2].add(new JButton("6"), new XYConstraints(200, 75, 0, 100));
        children[2].add(new JButton("5"), new XYConstraints(160, 125, 0, 100));
        children[2].add(new JButton("4"), new XYConstraints(120, 175, 0, 100));
        children[2].add(new JButton("3"), new XYConstraints(80, 225, 0, 100));
        children[2].add(new JButton("2"), new XYConstraints(40, 275, 0, 100));
        children[2].add(new JButton("1"), new XYConstraints(0, 325, 0, 100));

        children[3].add(new JButton("6"), new XYConstraints(200, 25, 0, 150));
        children[3].add(new JButton("5"), new XYConstraints(160, 75, 0, 150));
        children[3].add(new JButton("4"), new XYConstraints(120, 125, 0, 150));
        children[3].add(new JButton("3"), new XYConstraints(80, 175, 0, 150));
        children[3].add(new JButton("2"), new XYConstraints(40, 225, 0, 150));
        children[3].add(new JButton("1"), new XYConstraints(0, 275, 0, 150));

        //children[4],//children[5]...



        f.setSize(800, 600);
        f.setLocationRelativeTo(null);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);

    }

一个文件中的自定义布局:XYLayout

 public class XYLayout implements LayoutManager2, Serializable {

    private int width;
    private int height;
    Hashtable<Component, Object> info;
    static final XYConstraints defaultConstraints = new XYConstraints();

    public XYLayout() {
        info = new Hashtable<Component, Object>();
    }

    public XYLayout(int width, int height) {
        info = new Hashtable<Component, Object>();
        this.width = width;
        this.height = height;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("XYLayout [width=").append(width).append(", height=").append(height).append("]");
        return builder.toString();
    }

    public void addLayoutComponent(String s, Component component1) {
    }

    public void removeLayoutComponent(Component component) {
        info.remove(component);
    }

    public Dimension preferredLayoutSize(Container target) {
        return getLayoutSize(target, true);
    }

    public Dimension minimumLayoutSize(Container target) {
        return getLayoutSize(target, false);
    }

    public void layoutContainer(Container target) {
        Insets insets = target.getInsets();
        int count = target.getComponentCount();
        for (int i = 0; i < count; i++) {
            Component component = target.getComponent(i);
            if (component.isVisible()) {
                Rectangle r = getComponentBounds(component, true);
                component.setBounds(insets.left + r.x, insets.top + r.y, r.width, r.height);
            }
        }

    }

    public void addLayoutComponent(Component component, Object constraints) {
        if (constraints instanceof XYConstraints)
            info.put(component, constraints);
    }

    public Dimension maximumLayoutSize(Container target) {
        return new Dimension(0x7fffffff, 0x7fffffff);
    }

    public float getLayoutAlignmentX(Container target) {
        return 0.5F;
    }

    public float getLayoutAlignmentY(Container target) {
        return 0.5F;
    }

    public void invalidateLayout(Container container) {
    }

    public Rectangle getComponentBounds(Component component, boolean doPreferred) {
        XYConstraints constraints = (XYConstraints) info.get(component);
        if (constraints == null)
            constraints = defaultConstraints;
        Rectangle r = new Rectangle(constraints.getX(), constraints.getY(), constraints.getW(), constraints.getH());
        if (r.width <= 0 || r.height <= 0) {
            Dimension d = doPreferred ? component.getPreferredSize() : component.getMinimumSize();
            if (r.width <= 0)
                r.width = d.width;
            if (r.height <= 0)
                r.height = d.height;
        }
        return r;
    }

    public Dimension getLayoutSize(Container target, boolean doPreferred) {
        Dimension dim = new Dimension(0, 0);
        if (width <= 0 || height <= 0) {
            int count = target.getComponentCount();
            for (int i = 0; i < count; i++) {
                Component component = target.getComponent(i);
                if (component.isVisible()) {
                    Rectangle r = getComponentBounds(component, doPreferred);
                    dim.width = Math.max(dim.width, r.x + r.width);
                    dim.height = Math.max(dim.height, r.y + r.height);
                }
            }

        }
        if (width > 0)
            dim.width = width;
        if (height > 0)
            dim.height = height;
        Insets insets = target.getInsets();
        dim.width += insets.left + insets.right;
        dim.height += insets.top + insets.bottom;
        return dim;
    }

}

class XYConstraints implements Cloneable, Serializable {

    private int x;

    private int y;

    private int w;

    private int h;

    public XYConstraints() {
        this(0, 0, 0, 0);
    }

    public XYConstraints(int x, int y, int w, int h) {
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getW() {
        return w;
    }

    public void setW(int w) {
        this.w = w;
    }

    public int getH() {
        return h;
    }

    public void setH(int h) {
        this.h = h;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + h;
        result = prime * result + w;
        result = prime * result + x;
        result = prime * result + y;
        return result;
        // return x ^ y * 37 ^ w * 43 ^ h * 47;
    }

    public boolean equals(Object that) {
        if (that instanceof XYConstraints) {
            XYConstraints other = (XYConstraints) that;
            return other.x == x && other.y == y && other.w == w && other.h == h;
        } else {
            return false;
        }
    }

    public Object clone() {
        return new XYConstraints(x, y, w, h);
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("XYConstraints [x=").append(x).append(", y=").append(y).append(", w=").append(w).append(", h=").append(h).append("]");
        return builder.toString();
    }

我的第一次尝试是:

     for (y = 375; y > 0; y = y - 50)
     children[1].add(new JButton("1"), new XYConstraints(x, y, w, h));

     for (y = 325, x = 0; y > 0 && x < 280; y = y - 50, x = x + 40)
     children[2].add(new JButton("2"), new XYConstraints(x, y, w, 2 * h));

     for (y = 275, x = 0; y > 0 && x < 240; y = y - 50, x = x + 40)
     children[3].add(new JButton("3"), new XYConstraints(x, y, w, 3 * h));

但是缺少一些东西,例如“children[i]”的循环。我确信有更好的解决方案来改进循环任何改进或建议的想法?谢谢

【问题讨论】:

  • 您的第一次尝试是否有效,而您只是想消除进一步的重复?还是您的第一次尝试没有成功,您需要帮助?
  • 事实上,我正在寻找与儿童打交道的东西[i]。如果我有 10 个孩子,我必须写 10 个 for 循环。

标签: java swing loops layout layout-manager


【解决方案1】:

我编写自己的布局,因为现有的布局管理器不符合我的要求

想法不错,但您的实现不正确。您需要提供 x/y 值的事实意味着您没有使用布局管理器,而只是硬编码一些值。

相反,您需要向布局管理器提供信息来定义布局的参数,可能类似于:

MyLayout layout = new MyLayout(xSize, ySize, xOffset, yOffset);

因此,对于您将使用的第一个面板:

MyLayout layout = new MyLayout(50, 50, 0, 50);

这段代码表示每个组件都是 (50, 50)。当您将组件添加到面板时,您将 x 偏移更改为 0 并且 y 偏移 = -50。

您知道您有 8 个按钮,因此您可以使用数学计算面板的宽度/高度。然后,您可以在布局管理器中使用循环来定位每个组件。

所以现在您将组件添加到面板中,例如:

panel.add( new JButton("1") );
panel.add( new JButton("2") );
panel.add( new JButton("3") );

对于您可能使用的第二个面板:

MyLayout layout = new MyLayout(50, 100, 50, 50);

所以这一次意味着每个按钮知道的大小为 (50, 100) 并且每个按钮都放置在 (50, -50) 到前一个按钮的位置。

这就是布局管理器的创建方式。您不需要复杂的循环来构建添加到面板的每个组件的约束。这是布局管理器的工作。

【讨论】:

    【解决方案2】:

    你可以试试:

    for( int i=1; i<=3; i++ ) {
        x = 0;
        for( y=375-((i-1)*50; y>0; y-=50, x+=40 ) {
            children[i].add(new JButton((String)i), new XYConstraints(x, y, w, i*h));
        }
    }
    

    【讨论】:

    • 是的,我正在寻找谢谢!
    • @user3748551 - 我知道它可能会回答您的问题,但这不是一个好的解决方案。现在您正在布局管理器之外编写布局管理代码。花点时间学习如何正确编写布局管理器。
    • camickr 是正确的,这里最干净的关注点分离是编写一个独立的布局管理器,将每个按钮布置在上一个按钮上方 50 像素和前一个按钮右侧 40 像素,这样每次你调用 add() 布局管理器可以自动找出放置元素的位置。值得麻烦吗?在这种有限的情况下,我说不,即使这是最干净的关注点分离。但是我会将内部 for 循环分解为一个辅助方法(您可以将 children[i] 传递给该方法),以使其中的那部分更加模块化。
    • Is it worth the trouble? I say no in this limited case, - 我不同意 :) 如果你不厌其烦地尝试制作一个布局管理器,那就好好做吧。学习如何在一个简单的案例中编写布局管理器,它将在您将来需要时让更难的案例变得更容易。
    猜你喜欢
    • 2011-05-30
    • 2019-03-21
    • 1970-01-01
    • 1970-01-01
    • 2018-09-16
    • 2011-12-08
    • 2021-11-04
    相关资源
    最近更新 更多