如何动态地向复合控件添加 SWT 小部件?

5
我正在尝试在单击按钮时向复合组件添加文本框、按钮等部件。我已经尝试过,但只能动态地添加这些部件,而且只能添加到复合组件的大小范围内。我的JFace对话框有一个滚动复合组件,其中包含一个复合组件。在主复合组件中,我还有3个其他复合组件,我必须实现此功能,因此如果我向复合组件添加动态部件,则可能会扩展,但不应重叠到下方的现有复合组件,而应相应地调整其他复合组件,并且我应该能够在单击按钮时处理这些部件。之前有人尝试过动态添加和删除部件吗?我是新手,对Swt、Jface不熟悉。因此,是否有人可以在此分享他们的经验?我将发布我尝试过的代码。
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;


public class DynamicDialog extends Dialog {
    private Text text;
    private Text text_1;
    private Composite composite;

    /**
     * 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);

        composite = new Composite(scrolledComposite, SWT.NONE);
        composite.setLayout(new FormLayout());

        scrolledComposite.setContent(composite);
        scrolledComposite.setMinSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));


        final Composite composite_1 = new Composite(composite, SWT.NONE);
        composite_1.setLayout(new GridLayout(4, false));
        final FormData fd_composite_1 = new FormData();
        fd_composite_1.top = new FormAttachment(0);
        fd_composite_1.left = new FormAttachment(0, 10);
        fd_composite_1.bottom = new FormAttachment(0, 85);
        fd_composite_1.right = new FormAttachment(0, 430);
        composite_1.setLayoutData(fd_composite_1);

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

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

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

        Button btnDelete = new Button(composite_1, SWT.NONE);
        btnDelete.setText("delete");

        final Composite composite_2 = new Composite(composite, SWT.NONE);
        composite_2.setLayout(new GridLayout(2, false));
        final FormData fd_composite_2 = new FormData();
        fd_composite_2.bottom = new FormAttachment(100, -91);
        fd_composite_2.top = new FormAttachment(0, 91);
        fd_composite_2.right = new FormAttachment(100, -10);
        fd_composite_2.left = new FormAttachment(100, -74);
        composite_2.setLayoutData(fd_composite_2);
        new Label(composite_2, SWT.NONE);

        Button btnAdd = new Button(composite_2, SWT.NONE);
        btnAdd.setText("ADD");



        btnAdd.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {

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

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

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

                Button btnDelete = new Button(composite_1, SWT.NONE);
                btnDelete.setText("delete");

                //Point p0 = composite_1.getSize();
                //composite_1.setSize(SWT.DEFAULT,SWT.DEFAULT);
                composite_1.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){
    Display display = new Display();
    Shell shell =  new Shell(display);
    shell.setLayout(new FillLayout());

    DynamicDialog dd = new DynamicDialog(shell);
    dd.open();

}

}

我会收藏这个问题,因为我自己有一个非常类似的问题。https://dev59.com/8nnZa4cB1Zd3GeqPrY7u - Georgian
@GGrec 是的,这个问题困扰了我一个星期,我尝试了不同的方法,但是没有得到最好的结果。所以,我只是想看看是否有人能帮助我们的事业。谢谢! - Juseeth
@GGrec,我在网上找到一个例子,有点类似于我们的问题,滚动组合示例,你可以试试。在这个例子代码中,当我添加不同的组件时,它运行得很好,但是当我写一个单独的代码时,它就不起作用了。还有一件有趣的事情是,在滚动组合示例中,它把所有东西都创建在 SWT shell 上,而我使用的是 JFace 对话框。这会对我们正在做的事情产生影响吗? - Juseeth
ScrolledComposite通常很麻烦。你必须小心地将其与滚动组件包装在一起。但是,如果你花足够的时间去尝试,最终你会得出结论:你实际上可以在Dialog内部使用ScrolledComposite,并且它也会滚动。 - Georgian
1个回答

16

解决您的问题的方法是在每次添加/删除小部件时设置ScrolledComposite 的最小大小。您将使用ScrolledCompositesetMinSize(Point) API。同时,记得对滚动复合控件进行layout()操作,而不是它的子控件。子控件的布局将自动完成。

目前添加按钮会随着每个新添加的组件一起移动。如果您希望其不移动,请将其移到滚动复合内容之外。

此外,我稍微整理了一下您的代码,希望您不介意。 :-)

public class DynamicDialog extends Dialog 
{
    private int count = 1;

    public DynamicDialog(final Shell parent) 
    {
        super(parent);
    }

    @Override
    protected Control createDialogArea(final Composite parent) 
    {
        final Composite container = (Composite) super.createDialogArea(parent);
        container.setLayout(new FillLayout());

        final 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));

        final Composite composite_1 = new Composite(composite, SWT.NONE);
        composite_1.setLayout(new GridLayout(2, false));
        composite_1.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));

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

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

        final Composite composite_2 = new Composite(composite, SWT.NONE);
        composite_2.setLayout(new GridLayout(4, false));
        composite_2.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));

        final Composite composite_3 = new Composite(composite, SWT.NONE);
        composite_3.setLayout(new GridLayout());
        composite_3.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));

        final Button btnAdd = new Button(composite_3, SWT.NONE);
        btnAdd.setText("Add");
        btnAdd.addSelectionListener(new SelectionAdapter() 
        {
            @Override public void widgetSelected(final SelectionEvent e) 
            {
                final Label label2 = new Label(composite_2, SWT.NONE);
                label2.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
                label2.setText( String.valueOf(count++) );

                new Text(composite_2, SWT.BORDER).setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
                new Text(composite_2, SWT.BORDER).setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
                new Button(composite_2, SWT.NONE).setText("Delete");

                // DO THIS:
                scrolledComposite.layout(true, true);
                scrolledComposite.setMinSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
                // .. and it will work
            }
        });

        return container;
    }

    @Override
    protected void createButtonsForButtonBar(final 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(final String[] args)
    {
        final Shell shell = new Shell(new Display());
        shell.setLayout(new FillLayout());

        new DynamicDialog(shell).open();
    }
}

太好了,我不介意清理我的代码,我保留它是因为这只是一个粗略的估计。我怎么会错过那个?非常感谢你的解决方案,以及你的计数器解决了我的另一个问题,我原本以为删除时组合部分不会相应地被删除,但在将计数器放到标签上后,显示出我正在做正确的事情。 - Juseeth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接