【问题标题】:SWT Shell resize depending on childrenSWT Shell 根据子级调整大小
【发布时间】:2013-11-25 22:07:46
【问题描述】:

我正在处理这个Composite 画布,可以在上面添加和删除其他Composites。

我对整个布局概念的理解仍处于迷雾之中。

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

如果问题太模糊,请随时询问更多细节。另外,请尽量不要将我指向了解 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++) );
    }
}

趣事: 这个问题与to this other one, that was posted 9 minutes ago 相关。有人通灵或跟踪我。

【问题讨论】:

    标签: java swt eclipse-rcp jface


    【解决方案1】:

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

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

    根据发生的变化,您可以通过在 shell 的子 Composite 上调用 layout() 而侥幸逃脱。

    【讨论】:

    • 您的解决方案似乎适用于更复杂的示例。我想知道shell.setSize(Point) 在我的情况下是否是强制性的(基本上是pack(true))。我会在完成整个实施后回复你们。
    • pack(true) 和我的最后两行一样。我从中提取的代码还检查了 pack 无法完成的最小大小。
    • @greg-449 对于 JFace 组合框也是如此。我问了一个问题here
    • @SarasArya 这仅适用于 Shell。单个控件的大小取决于您使用的布局。
    • shell.pack(true) 解决了我在添加/删除子项时自动更改对话框大小的问题。谢谢
    【解决方案2】:

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

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

    Parent.layout(true)

    来自 swt api:

    public void layout(boolean changed)
    

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

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

    注意:布局不同于绘画。如果一个孩子被移动或调整大小使得父母中的一个区域被暴露,那么父母将绘画。如果没有孩子受到影响,则父母不会画画。

    参数: changed - 如果布局必须刷新其缓存,则为 true,否则为 false 抛出: SWTException - ERROR_WIDGET_DISPOSED - 如果接收器已被处置 ERROR_THREAD_INVALID_ACCESS - 如果没有从创建接收器的线程调用

    因此,在您的情况下,只要添加复合材料的父级上的 layout() 函数,它们就会对您有所帮助。

    【讨论】:

    • 在另一种情况下,我尝试在Shell 上调用layout。当时似乎没有工作。这是否也适用于Dialogs 和Wizards?调用 API 需要 多高
    • 我有一个我不久前写的代码的副本,做同样的事情,当我下班回家时,我会打开它,看看有什么不同。我确实记得有一些微妙之处我不得不玩弄直到它起作用。每次我制作一个新的复合材料时,其中一个确实是打电话给layout(true),但我会在几个小时内联系!除非我有灵感和记忆,否则会更快。
    • 好的,所以在重新阅读了您的问题以及您在底部提到的问题之后,我可能在这里感到困惑。主要问题是您根本看不到新的动态按钮吗?或者你制作太多后整个外壳不会调整大小?
    • 主要问题是容器布局良好,但外壳却不行。不管我要添加什么新孩子,在我的例子中,我写了带有标签的复合材料来证明一个观点。我只想打包 shell/wizard/dialog,以便我可以很好地查看所有组件。
    • 啊...这与我之前所做的有点不同。并且重新调用shell.pack(true) 并不能很好地调整所有内容的大小?
    【解决方案3】:

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

    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();
    
    }
    }
    

    【讨论】:

    • 显然这解决了你的问题,但不是我的。看到的事情是......当你添加很多时,它们往往会离开屏幕,你不能手动调整对话框的大小来查看它们。该对话框应自动调整大小-> 查看其他 2 个答案。 :-)
    • @GGrec 没错,现在这是我的问题,每当我在合成中创建新的小部件时,当它达到默认大小时,它会进入对话框并且滚动条不会不出现。你知道如何解决这个问题,因为我不太了解上面的解决方案吗? ,谢谢
    猜你喜欢
    • 2014-12-29
    • 2016-08-18
    • 1970-01-01
    • 2017-04-08
    • 2014-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多