ScrolledComposite 中的 SWT GridLayout 弄乱了组件的大小

SWT GridLayout inside ScrolledComposite messing up the size of the components

我有一个 window,它必须显示一个按钮列表,所有按钮都在彼此下方。 所有按钮都必须是特定尺寸的正方形(尺寸可以在 运行 时更改)。

这个简单的例子显示了所有的按钮。

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

        val scrollPanel = new ScrolledComposite(shell, SWT.V_SCROLL);
        scrollPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        scrollPanel.setLayout(new FillLayout());

        val gridPanel = new Composite(scrollPanel, SWT.NONE);
        val gridLayout = new GridLayout(1, false);
        gridPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        gridPanel.setLayout(gridLayout);
        scrollPanel.setContent(gridPanel);

        val blue = display.getSystemColor(SWT.COLOR_BLUE);
        val red = display.getSystemColor(SWT.COLOR_RED);
        scrollPanel.setBackground(blue);
        gridPanel.setBackground(red);

        val exitButton = new Button(gridPanel, SWT.PUSH);
        exitButton.setText("Exit");
        exitButton.addListener(SWT.Selection, touchEvent -> shell.dispose());

        for (int i = 1; i <= 10; i++)
        {
            val button = new Button(gridPanel, SWT.PUSH);
            button.setText("Item: " + i);
            button.setSize(60, 60);
            gridPanel.setSize(gridPanel.computeSize(SWT.DEFAULT, SWT.DEFAULT));
        }

        shell.setSize(100, 700);

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

但是,每当我执行 gridPanel.computeSize() 时,按钮都会丢失由 button.setSize() 设置的大小。

当我在添加按钮后删除 gridPanel.setSize() 时,大小将为 0,gridPanel 根本不会显示。

当我在 scrollPanel 上设置 gridLayout 并向其添加按钮时,只显示一个按钮。 (最后一个按钮,如果我使用 setContent() 和第二个(无论出于何种原因),如果我不使用 setContent() 并且只依赖于按钮的构造函数。)

此时此刻,我完全没有选择,所以如果有人能解决这个问题,那么请继续。

如果您使用布局(您应该使用),则不得使用 setSize() 或以其他方式干扰布局。

使用 GridDatawidthHintheightHint 来控制按钮的大小。

例如:

GridData gridData = new GridData( SWT.BEGINNING, SWT.CENTER, false, false );
gridData.widthHint = 60;
gridData.heightHint = 60;
button.setLayoutData( gridData );

首先,setSize 只有在您不使用布局(绝对定位)时才能正常工作。

如果您使用布局,它会根据布局本身以及您定义组件布局数据的方式自动设置组件大小。

一般来说,强烈建议使用布局而不是绝对定位。

GridLayout的情况下,您可以在其GridData中通过widthHintheightHint指定组件大小,例如:

Button button = new Button(gridPanel, SWT.PUSH);
button.setText("Item: " + i);
GridData buttonLayoutData = new GridData();
buttonLayoutData.widthHint = 60;
buttonLayoutData.heightHint = 60;
button.setLayoutData(buttonLayoutData);

其他观察:

  • 要使 ScrollComposite 正常工作,您应该添加以下行:

    scrollPanel.setExpandHorizontal(true);
    scrollPanel.setExpandVertical(true);
    scrollPanel.setMinSize(gridPanel.computeSize(SWT.DEFAULT, SWT.DEFAULT));
    

    特别是,setMinSize 会告诉 ScrollComposite 它应该使滚动条显示在什么尺寸。

  • 如果父布局是 FillLayout,则不应在其子布局上设置布局数据。它不会做任何事情,因为它不是预期的。所以你应该从 scrollPanelgridPanel.

  • 中删除 setLayoutData
  • 如果以后想改变按钮的大小,只需要获取其布局数据,修改提示并要求组件进行布局(也不要忘记通知滚动条更改为 setMinSize):

    GridData buttonLayoutData = (GridData) button.getLayoutData();
    buttonLayoutData.widthHint = 40;
    buttonLayoutData.heightHint = 40;
    button.requestLayout();
    scrollPanel.setMinSize(gridPanel.computeSize(SWT.DEFAULT, SWT.DEFAULT));