Java SWT Shell 根据孩子调整大小

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20204381/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 00:15:10  来源:igfitidea点击:

SWT Shell resize depending on children

javaswteclipse-rcpjface

提问by GGrec

I'm working on this Compositecanvas on which other Composites may be added and removed.

我正在这个Composite画布上工作,Composite可以添加和删除其他s。

My understanding of how the whole laying-out concept is still in the fog.

我对整个布局概念的理解仍然模糊不清。

When children are added to the container, given the fact that the container has a GridDatawhich fills in the parent, shouldn't the parent also know that the child resized? Children remain hidden after their container has been laid out, because of the shell (top parent).

当孩子被添加到容器中时,考虑到容器有一个GridData填充父级的事实,父级不应该也知道子级调整了大小吗?由于外壳(顶部父级),子项在其容器布置后仍处于隐藏状态。

If the question is too vague, do not hesitate to ask for more details. Also, try your best not pointing me to the Understanding layouts in SWTarticle.

如果问题太模糊,请不要犹豫,询问更多细节。另外,请尽量不要将我指向了解 SWT 中的布局一文。

/**
 * 
 * @author ggrec
 *
 */
public class SSCCE
{

    // ==================== 2. Instance Fields ============================

    private Composite componentContainer;

    private int componentCount = 0;

    // ==================== 3. Static Methods =============================

    public static void main(final String[] args)
    {
        new SSCCE();
    }

    // ==================== 4. Constructors ===============================

    private SSCCE()
    {
        final Display display = new Display();
        final Shell shell = new Shell(display);
        shell.setLayout(new GridLayout(1, false));

        createContents(shell);

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

    // ==================== 5. Creators ===================================

    private void createContents(final Composite parent)
    {
        parent.setLayout(new GridLayout());
        parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        final Button button = new Button(parent, SWT.PUSH);
        button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        button.setText("Add New Component");

        button.addSelectionListener(new SelectionAdapter()
        {
            @Override public void widgetSelected(final SelectionEvent e)
            {
                addNewComponent();

                componentContainer.layout();
            }
        });

        componentContainer = new Composite(parent, SWT.BORDER);
        componentContainer.setLayout(new GridLayout());
        componentContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    }

    // ==================== 6. Action Methods =============================

    private void addNewComponent()
    {
        final Composite component = new Composite(componentContainer, SWT.BORDER);
        component.setLayout(new FillLayout());
        component.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));

        final Label label = new Label(component, SWT.NONE);
        label.setText( String.valueOf(componentCount++) );
    }
}

Fun fact: This question is veeeery related to this other one, that was posted 9 minutes ago. Someone is either psychic or stalking me.

有趣的事实:这个问题与9 分钟前发布的另一个问题非常相关。有人要么通灵,要么在跟踪我。

采纳答案by greg-449

To get the Shellto resize you need to layout everything and recalculate its size:

Shell调整大小,您需要布局所有内容并重新计算其大小:

shell.layout(true, true);

final Point newSize = shell.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);  

shell.setSize(newSize);

You may be able to get away with calling layout()on a child Compositeof the shell depending on what has changed.

您可以根据更改的内容调用shelllayout()的子级Composite

回答by WillBD

The secret here to probably solve your problem is TELLING the parent that the children have been resized. So, no, they do not automatically know it has happened.

这里可能解决您的问题的秘诀是告诉父母孩子已经调整大小。所以,不,他们不会自动知道它已经发生了。

the way to fix this, is to call the:

解决这个问题的方法是调用:

Parent.layout(true)

Parent.layout(true)

from the swt api:

来自 swt api:

public void layout(boolean changed)

If the receiver has a layout, asks the layout to lay out (that is, set the size and location of) the receiver's children. If the argument is true the layout must not rely on any information it has cached about the immediate children. If it is false the layout may (potentially) optimize the work it is doing by assuming that none of the receiver's children has changed state since the last layout. If the receiver does not have a layout, do nothing.

If a child is resized as a result of a call to layout, the resize event will invoke the layout of the child. The layout will cascade down through all child widgets in the receiver's widget tree until a child is encountered that does not resize. Note that a layout due to a resize will not flush any cached information (same as layout(false)).

Note: Layout is different from painting. If a child is moved or resized such that an area in the parent is exposed, then the parent will paint. If no child is affected, the parent will not paint.

如果接收者有布局,则要求布局布局(即设置其大小和位置)接收者的孩子。如果参数为真,则布局不得依赖于它已缓存的有关直接子项的任何信息。如果它是假的,布局可以(潜在地)通过假设接收者的子节点自上次布局以来没有改变状态来优化它正在做的工作。如果接收器没有布局,则什么也不做。

如果由于调用布局而调整了子项的大小,则 resize 事件将调用子项的布局。布局将通过接收器小部件树中的所有子小部件向下级联,直到遇到未调整大小的子部件。请注意,由于调整大小而导致的布局不会刷新任何缓存信息(与 layout(false) 相同)。

注意:布局不同于绘画。如果移动子项或调整其大小以暴露父项中的某个区域,则父项将进行绘制。如果没有孩子受到影响,父母就不会画画。

Parameters:
    changed - true if the layout must flush its caches, and false otherwise
Throws:
    SWTException -
    ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver

So in your case, calling the layout()function on the parent of your composites anytime they are added should help you out.

因此,在您的情况下,layout()在添加复合材料的任何时候在其父级上调用该函数应该对您有所帮助。

回答by Juseeth

As you've said our both questions are similar, I'm posting the solution what I've achieved. Let me know if this helps you.

正如您所说,我们的两个问题都很相似,我正在发布我所取得的解决方案。如果这对您有帮助,请告诉我。

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Combo;


public class DynamicDialog extends Dialog {
   private Composite composite_2;


    /**
     * Create the dialog.
     * @param parentShell
     */
    public DynamicDialog(Shell parentShell) {
        super(parentShell);
    }

    /**
     * Create contents of the dialog.
     * @param parent
     */
    @Override
    protected Control createDialogArea(Composite parent) {
        Composite container = (Composite) super.createDialogArea(parent);
        container.setLayout(new FillLayout(SWT.HORIZONTAL));

        ScrolledComposite scrolledComposite = new ScrolledComposite(container, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
        scrolledComposite.setExpandHorizontal(true);
        scrolledComposite.setExpandVertical(true);

        final Composite composite = new Composite(scrolledComposite, SWT.NONE);
        composite.setLayout(new GridLayout(1, false));
        scrolledComposite.setContent(composite);
        scrolledComposite.setSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));

        Composite composite_1 = new Composite(composite, SWT.NONE);
        composite_1.setLayout(new GridLayout(2, false));
        GridData gd_composite_1 = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
        gd_composite_1.heightHint = 49;
        gd_composite_1.widthHint = 427;
        composite_1.setLayoutData(gd_composite_1);

        Label lblDefault = new Label(composite_1, SWT.NONE);
        lblDefault.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
        lblDefault.setText("Default:");

        Combo combo = new Combo(composite_1, SWT.NONE);
        combo.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1));

        composite_2 = new Composite(composite, SWT.NONE);
        composite_2.setLayout(new GridLayout(4, false));
        GridData gd_composite_2 = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
        /*gd_composite_2.heightHint = 32;
        gd_composite_2.widthHint = 426;*/
        composite_2.setLayoutData(gd_composite_2);

        Composite composite_3 = new Composite(composite, SWT.NONE);
        composite_3.setLayout(new GridLayout(1, false));
        GridData gd_composite_3 = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
        gd_composite_3.heightHint = 38;
        gd_composite_3.widthHint = 427;
        composite_3.setLayoutData(gd_composite_3);

        Button btnAdd = new Button(composite_3, SWT.NONE);
        btnAdd.setText("Add");
        btnAdd.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {


                Label label2 = new Label(composite_2, SWT.NONE);
                label2.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
                        false, 1, 1));
                label2.setText("1");

                Text text_12 = new Text(composite_2, SWT.BORDER);
                text_12.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
                        false, 1, 1));

                Text text13 = new Text(composite_2, SWT.BORDER);
                text13.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
                        false, 1, 1));

                Button btnDelete = new Button(composite_2, SWT.NONE);
                btnDelete.setText("delete");
                composite_2.layout(true);


                composite_2.layout();
                // Point p = composite.getSize();
                // composite.setSize(SWT.DEFAULT,SWT.DEFAULT);
                // composite.setSize(p);

                composite.layout();


            }
        });






        return container;
    }

    /**
     * Create contents of the button bar.
     * @param parent
     */
    @Override
    protected void createButtonsForButtonBar(Composite parent) {
        createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
                true);
        createButton(parent, IDialogConstants.CANCEL_ID,
                IDialogConstants.CANCEL_LABEL, false);
    }

    /**
     * Return the initial size of the dialog.
     */
    @Override
    protected Point getInitialSize() {
        return new Point(450, 300);
    }

public static void main(String[] args){

    Shell shell =  new Shell(new Display());
    //shell.setLayout(new FillLayout());
    DynamicDialog dd = new DynamicDialog(shell);
    dd.open();

}
}