JPanels不完全伸展占用的可用空间 [英] JPanels don't completely stretch to occupy the available space

查看:164
本文介绍了JPanels不完全伸展占用的可用空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个面板,我把几个小型面板,并排侧,用不同大小和颜色,他们应该占据整个父面板(​​水平)。

I have a panel where I place several mini-panels, side-by-side, with different sizes and colors, and they should occupy the entire parent panel (horizontally).

为此,我用的BorderLayout(父面板),并为BoxLayout的子面板,我把所有的小板(见下文code)。它的工作和行为正确uppon调整和一切。然而,如微型板的数目变大时,会出现一个奇怪的行为:空的空间出现在父面板的端

For this I use BorderLayout (for the parent panel), and BoxLayout for a sub-panel where I place all the mini-panels (see code below). It does work and behave correctly uppon resizing and everything. However, as the number of mini-panels becomes larger, a strange behaviour occurs: empty space appears at the end of the parent panel.

我想我找到了,这是在布局经理streching错误,因为为了STRETCH时面板,布局管理器试图将单个像素添加到每个迷你面板。然而,当微型板的数量大时,增加一个像素到每一位将导致加入许多像素和超越母体的尺寸。因此,布局管理器结束不加入任何像素到任何微型面板,产生空的空间。

I think I found that this is a streching bug in the layout managers, because in order to strech the panels, the layout manager tries to add a single pixel to each mini-panel. However, when the number of mini-panels is large, adding a single pixel to every one will result in adding many pixels and going beyond the size of the parent. Thus, the layout manager ends up not adding any pixels to any mini-panel, resulting in the empty space.

下面是我的SSCCE:
(试运行,并且streching窗口,了解问题)

Here is my SSCCE: (try running, and streching the window, to understand the problem)

package com.myPackage;

import java.awt.*;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ColoredPanels extends JPanel
{
    /* Content information. */
    private Vector<Integer> partitions;
    private Vector<Color> colors;

    /* Panel where the content panels will go. */
    private JPanel contentHolder;

    private final int defaultHeight = 20;

    public ColoredPanels(Vector<Integer> partitions, Vector<Color> colors)
    {
        assert partitions != null;
        assert !partitions.isEmpty();
        assert colors != null;
        assert !colors.isEmpty();
        assert colors.size() == partitions.size();

        this.partitions = partitions;
        this.colors = colors;

        /* Set layout manager. */
        setLayout(new BorderLayout());

        /* Create the content holder. */
        contentHolder = new JPanel();
        contentHolder.setLayout(new BoxLayout(contentHolder, BoxLayout.X_AXIS));
        this.add(contentHolder, BorderLayout.NORTH);

        /* Fill content holder with colored panels. */
        createPanels();
    }

    private void createPanels()
    {
        assert partitions != null;
        assert !partitions.isEmpty();
        assert colors != null;
        assert !colors.isEmpty();
        assert colors.size() == partitions.size();

        for (int i = 0; i < partitions.size(); i++)
        {
            JPanel newPanel = new JPanel();
            newPanel.setBackground(colors.get(i));
            newPanel.setPreferredSize(new Dimension(partitions.get(i), defaultHeight));
            newPanel.setMinimumSize(new Dimension(1, defaultHeight));
            contentHolder.add(newPanel);
        }
    }

    public static void main(String[] in)
    {
        Vector<Integer> sizes = new Vector<Integer>();
        Vector<Color> cols = new Vector<Color>();

        /* Make 100 random sizes, and use two colors. */
        for (int i = 0; i < 100; i++)
        {
            int size = (int)Math.round(1 + Math.random() * 10);
            sizes.add(size);
            cols.add((i%2 == 0)? Color.red : Color.green);
        }

        ColoredPanels panels = new ColoredPanels(sizes, cols);
        panels.setBorder(BorderFactory.createLineBorder(Color.yellow, 1));

        JFrame newFrame = new JFrame();
        newFrame.getContentPane().add(panels);
        newFrame.pack();
        newFrame.setVisible(true);
    }
}

我如何避免这种情况?我希望我的面板占据了整个容器。

How do I avoid this behaviour? I want my panels to occupy the whole container.

编辑:
微型板旨在具有(一旦这被解决)鼠标听众。因此,涂装解决方案是可惜的是可以避免的。

The mini-panels are intended to have (once this is resolved) mouse listeners. Thus, painting solutions are unfortunatelly avoidable.

推荐答案

布局问题都是由...布局管理解决:-)如果一个人不是你想要它做的事情,实现你想要的行为。

Layout problems are solved by ... LayoutManagers :-) If one doesn't what you want it to do, implement the behaviour you want.

因此​​,如果核心的BoxLayout只是忽略由于舍入误差,子像素并根据需要将其分发给那些像素。一个非常原始简单的例子:

So if the core BoxLayout simply ignores pixels due to rounding errors, subclass and make it distribute those pixels as needed. A very raw quick example:

public static class XBoxLayout extends BoxLayout {

    enum Strategy {
        NONE,
        STRETCH_LAST,
        DISTRUBUTE
    }

    private Strategy strategy;

    public XBoxLayout(Container target, int axis, Strategy strategy) {
        super(target, axis);
        this.strategy = strategy;
    }


    @Override
    public void layoutContainer(Container target) {
        super.layoutContainer(target);
        if (Strategy.NONE == strategy) return;
        Insets targetInsets = target.getInsets();
        int targetSize = target.getWidth() - targetInsets.left - targetInsets.right;
        int childSum = 0;
        for (Component child : target.getComponents()) {
            childSum += child.getWidth();
        }
        if (targetSize > childSum) {
            int excess = targetSize - childSum;
            distribute(target, excess);
        }
    }


    private void distribute(Container target, int excess) {
        System.out.println("childCount/rounding excess " + target.getComponentCount() + "/" + excess);
        if (Strategy.STRETCH_LAST == strategy) {
            Component lastChild = target.getComponent(target
                    .getComponentCount() - 1);
            lastChild.setSize(lastChild.getWidth() + excess,
                    lastChild.getHeight());
        } else {
            int firstToDistribute = target.getComponentCount() - excess;
            int summedOffset = 0;
            for(int index = firstToDistribute; index < target.getComponentCount(); index++) {
                Component child = target.getComponent(index);
                Rectangle bounds = child.getBounds();
                bounds.x += summedOffset++;
                bounds.width += 1;
                child.setBounds(bounds);
            }
        }
    }

}

这篇关于JPanels不完全伸展占用的可用空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆