Java 最后一个元素占据多余水平空间的SWT行布局?

Java 最后一个元素占据多余水平空间的SWT行布局?,java,layout,swt,Java,Layout,Swt,我在水平行布局中有两个元素。 我可以为第二个元素(例如200像素)指定一个(最小值)。此外 a) 如果壳的总宽度太小,则第二个图元将换行到新行。这在行布局中运行良好 b) 如果总数为“大”,则第二个(=最后一个)元素应占据多余的水平空间 b)是否可以使用行布局?或者我是否需要使用GridLayout并自行实现包装(例如,根据元素的大小,在网格布局中使用一列或两列) 行布局不支持您正在查找的内容。我建议使用GridLayout,并按照您的建议调整侦听器的大小,或者实现您自己的布局。我第一次尝试编写

我在水平
行布局中有两个元素。
我可以为第二个元素(例如200像素)指定一个(最小值)。此外

a) 如果壳的总宽度太小,则第二个图元将换行到新行。这在
行布局
中运行良好

b) 如果总数为“大”,则第二个(=最后一个)元素应占据多余的水平空间

b)是否可以使用
行布局
?或者我是否需要使用
GridLayout
并自行实现包装(例如,根据元素的大小,在网格布局中使用一列或两列)


行布局不支持您正在查找的内容。我建议使用
GridLayout
,并按照您的建议调整侦听器的大小,或者实现您自己的布局。

我第一次尝试编写一个自定义布局,结果很难。基于
GridLayout
的第二种策略更简单。下面是自定义的
组合
的初稿,该组合将其
GridLayout
的列数切换为一列或两列,具体取决于其子级的大小

(我在调整分区大小时仍然存在闪烁问题。)


我的自定义布局仍然存在问题。也许你可以看看我的相关问题:
public class RowLayoutDemo {

    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setLayout(new RowLayout());

        Text firstElement = new Text(shell, SWT.NONE);
        firstElement.setText("firstElement");

        Text secondElement = new Text(shell, SWT.NONE);
        secondElement.setText("secondElement");
        secondElement.setBackground(new Color(null, 200, 0, 0));

        int minWidth = 200;
        RowData rowData = new RowData();
        rowData.width = minWidth;
        secondElement.setLayoutData(rowData);

        shell.pack();
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }
}
package org.treez.core.adaptable.composite;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Layout;

/**
 * A row composite for only two children. If the children are too large for a single line, the second child is wrapped
 * on a second line. The second child always grabs excess horizontal space. This composite automatically sets the
 * LayoutData of its children. Therefore the LayoutData of the children should not be set manually.
 */
public class GrabbingRowComposite extends Composite {

    //#region ATTRIBUTES

    private int widthHintForFirstChild = 80;

    private int minWidthForSecondChild = 200;

    private boolean isSingleLine = true;

    //#end region

    //#region CONSTRUCTORS

    public GrabbingRowComposite(Composite parent) {
        super(parent);
        super.setLayout(createLayout());

        if (parent.getLayout() instanceof GridLayout) {
            GridData gridData = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
            setLayoutData(gridData);
        }

    }

    //#end region

    //#region METHODS

    private GridLayout createLayout() {

        //create default layout for single line
        GridLayout gridLayout = new GridLayout(2, false);

        //change layout to use several lines if required
        this.addControlListener(new ControlAdapter() {

            @Override
            public void controlResized(ControlEvent e) {
                adaptLayout();
            }
        });

        return gridLayout;
    }

    private void adaptLayout() {

        int totalWidth = this.getBounds().width;

        Control[] children = getChildren();
        if (children.length < 2) {
            return;
        }

        Control firstChild = children[0];
        Control secondChild = children[1];
        int firstChildWidth = children[0].getBounds().width;

        setWidthHintForFirstChild(firstChild);
        setGrapHorizontalSpaceForSecondChild(secondChild);

        boolean isTooSmallForOneLine = totalWidth < firstChildWidth + minWidthForSecondChild;
        if (isTooSmallForOneLine) {
            setTwoLineLayout();
        } else {
            setSingleLineLayout();
        }
    }

    private void setTwoLineLayout() {
        if (isSingleLine) {
            super.setLayout(new GridLayout(1, false));
            updateLayoutOfParentAndGrandParent();
            isSingleLine = false;
        }
    }

    private void setSingleLineLayout() {
        if (!isSingleLine) {
            super.setLayout(new GridLayout(2, false));
            updateLayoutOfParentAndGrandParent();
            isSingleLine = true;
        }
    }

    private void setWidthHintForFirstChild(Control firstChild) {
        GridData firstGridData = new GridData();
        firstGridData.widthHint = widthHintForFirstChild;
        firstChild.setLayoutData(firstGridData);
    }

    private static void setGrapHorizontalSpaceForSecondChild(Control secondChild) {
        GridData secondGridData = new GridData(SWT.FILL, SWT.FILL, true, false);
        secondChild.setLayoutData(secondGridData);
    }

    private void updateLayoutOfParentAndGrandParent() {
        Composite parent = getParent();
        if (parent != null) {
            parent.layout(true);
            Composite grandParent = parent.getParent();
            if (grandParent != null) {
                grandParent.layout(true);
            }
        }
    }

    //#end region

    //#region ACCESSORS

    @Override
    public void setLayout(Layout layout) {
        throw new IllegalStateException("The layout of this composite must not be changed");
    }

    //#end region

}
package org.treez.core.adaptable.composite;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.Section;

public class GrabbingRowCompositeDemo {

    public static void main(String[] args) {

        Shell shell = createShell();

        shell.setSize(500, 300);

        Section section = createSection(shell);

        Composite parentComposite = createParentComposite(section);

        createRow(parentComposite, "first");

        createRow(parentComposite, "second");

        createRow(parentComposite, "third");

        section.clientVerticalSpacing = 0;

        showUntilClosed(shell);

    }

    private static Shell createShell() {
        Display display = new Display();
        Shell shell = new Shell(display);

        GridLayout shellGridLayout = new GridLayout(1, false);
        shell.setLayout(shellGridLayout);
        return shell;
    }

    private static Section createSection(Shell shell) {
        Section section = new Section(
                shell,
                ExpandableComposite.TWISTIE | //
                        ExpandableComposite.EXPANDED | //
                        ExpandableComposite.TITLE_BAR | //
                        ExpandableComposite.CLIENT_INDENT);

        GridData gridData = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
        section.setLayoutData(gridData);
        return section;
    }

    private static Composite createParentComposite(Section section) {

        Composite parentComposite = new Composite(section, SWT.NONE);
        section.setClient(parentComposite);

        parentComposite.setBackground(new Color(null, 0, 0, 255));

        GridData gridData = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
        parentComposite.setLayoutData(gridData);

        GridLayout gridLayout = new GridLayout(1, false);
        parentComposite.setLayout(gridLayout);

        return parentComposite;
    }

    private static Composite createRow(Composite parent, String text) {

        GrabbingRowComposite row = new GrabbingRowComposite(parent);
        row.setBackground(new Color(null, 255, 255, 255));

        Label label = new Label(row, SWT.NONE);
        label.setText(text);

        Button checkBox = new Button(row, SWT.CHECK);
        checkBox.setBackground(new Color(null, 255, 0, 0));

        return row;

    }

    private static void showUntilClosed(Shell shell) {

        shell.open();
        Display display = Display.getCurrent();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        display.dispose();
    }

}