StackLayout中的SWT文本小部件 - 切换顶部控件时无法调整高度

时间:2015-06-07 05:48:40

标签: java layout swt

我在JFace对话框中有一个SWT Composite。在复合材料的一行中,我有一个垂直堆叠的4个按钮组。它旁边是一个Text小部件,需要通过用户输入在多行和单行之间来回切换。

我在StackLayout中有两个不同的Text小部件,我根据需要显示一个或另一个。但我找不到一种方法来调整Stack Composite和Text小部件的高度,具体取决于哪个Text是顶级控件。在单模式下我只需要一行高度,并且在多模式下填充与它旁边的组相同的垂直空间。当我创建Composite时,我可以将Text的高度调整为这些条件中的任何一个,但是当我从一个Text切换到另一个Text时,他们不会调整它们的高度。

这是一个代码段,导致文本小部件总是太高,在单一模式下永远不会缩小到一行高度。

这是复合

        @Override
        protected Control createDialogArea(Composite parent) {
            container = (Composite) super.createDialogArea(parent);
            GridDataFactory.fillDefaults().grab(true, true).applyTo(container);
            GridLayoutFactory.fillDefaults().numColumns(2).margins(5, 5).applyTo(container);

            Group group = new Group(container, SWT.NONE);
            GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true,  true).applyTo(group);
            GridLayoutFactory.fillDefaults().applyTo(group);        
            for (M_ATTRIBUTE attr : M_ATTRIBUTE.values()) {
                Button button = new Button(group, SWT.CHECK);
                GridDataFactory.fillDefaults().applyTo(button);
                button.setText(attr.getDisplayValue());
            }

            stack = new Composite(container, SWT.NONE);
            GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(stack);
            stackLayout = new StackLayout();
            stack.setLayout(stackLayout);
            valueTextMulti = new Text(stack, SWT.BORDER | SWT.MULTI);
            GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(valueTextMulti);
            valueTextMulti.addModifyListener(valueTextModifyListener);

            valueTextSingle = new Text(stack, SWT.BORDER | SWT.SINGLE);
            GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(valueTextSingle);
            valueTextSingle.addModifyListener(valueTextModifyListener);

            stackLayout.topControl = valueTextMulti;

            return container;
        }

这里有一个switch语句,显示我在单行和多行Text Widgets之间切换的方法。

        @Override
        public void selectionChanged(SelectionChangedEvent event) {
                IStructuredSelection sel = (IStructuredSelection) event.getSelection();
                M_DATA_TYPE type = (M_DATA_TYPE) sel.getFirstElement();
                switch (type) {
                case LIST:
                case HASH_TABLE:
                    stackLayout.topControl = valueTextMulti;
                    setNumRows(valueTextMulti, 10);
                    ((GridData) valueTextMulti.getLayoutData()).verticalAlignment = SWT.FILL;
                    ((GridData) valueTextMulti.getLayoutData()).grabExcessVerticalSpace = true;
                    ((GridData) stack.getLayoutData()).grabExcessVerticalSpace = true;
                    container.getParent().layout();
                    break;
                default:
                    stackLayout.topControl = valueTextSingle;
                    ((GridData) valueTextSingle.getLayoutData()).verticalAlignment = SWT.TOP;
                    ((GridData) valueTextSingle.getLayoutData()).grabExcessVerticalSpace = false;
                    ((GridData) stack.getLayoutData()).grabExcessVerticalSpace = false;
                    setNumRows(valueTextSingle, 1);
                    container.getParent().layout();
                    break;
                }
            }

以下是根据another StackOverflow post从字符行调整文本高度的方法。

protected void setNumRows(Text text, int rows) {
            GC gc = new GC(text);
            try
            {
                gc.setFont(text.getFont());
                FontMetrics fm = gc.getFontMetrics();

                int height = rows * fm.getHeight();
                text.setSize(text.getSize().x, height);
                text.getParent().layout();
            }
            finally
            {
                gc.dispose();
            }
        }

1 个答案:

答案 0 :(得分:0)

我通过在StackLayout组合内创建其他组合来实现它,每个Text小部件实例都有一个。每个Text小部件都有固定的布局数据,一个使用align = SWT.FILL,另一个使用SWT.TOP。然后我只是在StackLayout中切换容器组合而不是切换Text小部件。这具有不需要直接设置小部件高度的附加优点。切换内容后,还必须在StackLayout组合上调用layout()。在层次结构中较高的容器上调用layout()不起作用。

这是我修改后的代码:

@Override
protected Control createDialogArea(Composite parent) {
    container = (Composite) super.createDialogArea(parent);
    GridDataFactory.fillDefaults().grab(true, true).applyTo(container);
    GridLayoutFactory.fillDefaults().numColumns(2).margins(5, 5).applyTo(container);

    Group group = new Group(container, SWT.NONE);
    GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true,  false).applyTo(group);
    GridLayoutFactory.fillDefaults().applyTo(group);        
    for (M_ATTRIBUTE attr : M_ATTRIBUTE.values()) {
        Button button = new Button(group, SWT.CHECK);
        GridDataFactory.fillDefaults().applyTo(button);
        button.setText(attr.getDisplayValue());
        this.buttons.put(attr, button);
    }
    stack = new Composite(container, SWT.NONE);
    GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(stack);
    stackLayout = new StackLayout();
    stack.setLayout(stackLayout);               
    compMultiLine = new Composite(stack, SWT.NONE);
    GridDataFactory.fillDefaults().applyTo(compMultiLine);
    GridLayoutFactory.fillDefaults().applyTo(compMultiLine);
    valueTextMulti = new Text(compMultiLine, SWT.BORDER | SWT.MULTI |SWT.WRAP);
    GridDataFactory.fillDefaults().grab(true, true).applyTo(valueTextMulti);
    valueTextMulti.addModifyListener(valueTextModifyListener);              
    compSingleLine = new Composite(stack, SWT.NONE);
    GridDataFactory.fillDefaults().applyTo(compSingleLine);
    GridLayoutFactory.fillDefaults().applyTo(compSingleLine);
    valueTextSingle = new Text(compSingleLine, SWT.BORDER | SWT.SINGLE | SWT.WRAP);
    GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(valueTextSingle);
    valueTextSingle.addModifyListener(valueTextModifyListener);         
    stackLayout.topControl = compMultiLine;
    return container;
}


@Override
public void selectionChanged(SelectionChangedEvent event) {
    IStructuredSelection sel = (IStructuredSelection) event.getSelection();
    M_DATA_TYPE type = (M_DATA_TYPE) sel.getFirstElement();
    switch (type) {
    case LIST:
    case HASH_TABLE:
        stackLayout.topControl = compMultiLine;
        stack.layout();
        break;
    default:
        stackLayout.topControl = compSingleLine;
        stack.layout();
        break;
    }
}