隐藏 GridLayout 列和剩余列间距
Hide GridLayout column and remaining column spacing
tl;dr 有没有一种好方法可以隐藏 GridLayout
中的列并隐藏父级 Composite
中剩余的列间距?
我在 GridLayout
中有一个包含多个列的组合。一列是一个 Composite
和一个 StackLayout
,这样我就可以 hide/show Composite
.
例如:
为了完成 hiding/showing,我一直在 GridData
上设置 exclude
属性,在 StackLayout
上设置 topControl
属性:
// To hide
stackLayout.topControl = null;
stackComposite.setVisible(false);
((GridData) stackComposite.getLayoutData()).exclude = true;
现在,当我隐藏中间 Composite
时,我看到额外的 space 出现在行的远端。
这大概是因为baseComposite
上的GridLayout
的列数还是一样的,所以我们看到的是一个宽度为0的列,两边指定的列间距.
为了解决这个问题,我提出了几个(不理想的)解决方案:
Decrement/increment时的列数hiding/showing.
我们不使用 exclude
属性,而是用 StackLayout
覆盖 Composite
并将 computeSize(...)
函数更改为 return 0,或者根据我们是否希望它出现来计算实际大小。 (这是迄今为止我最不喜欢的选项,我什至觉得写它都很糟糕)
将基础 Composite
上的 horizontalSpacing
设置为 0,而不是使用每个列内的间距 Composite
来指定间距。隐藏时看起来像这样:
选项 1 到目前为止是最吸引人的,但是在尝试保持代码模块化时这里有一个明显的缺点。例如,如果每个列的 Composite
由某个可重用组件设置,则 decrementing/incrementing 列计数取决于该组件知道其父 Composite
具有 GridLayout
- 不是一个安全的假设!
选项2我坚决不喜欢。
选项 3 并不可怕,但它仍然感觉像是对间距和边距的误用。另外,回到模块化的观点,其他列组件将负责影响更大视图的间距,而不是让更大的视图决定间距。
所以我的问题归结为:还有比这三个更好的选择吗?
MCVE 用于获取上图:
public class MCVE {
final Display display;
final Shell shell;
public MCVE() {
display = new Display();
shell = new Shell(display);
shell.setLayout(new GridLayout());
shell.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
final Composite baseComposite = new Composite(shell, SWT.NONE);
baseComposite.setLayout(new GridLayout(3, false));
baseComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
baseComposite.setBackground(new Color(display, new RGB(125, 125, 255)));
final Composite contentComposite1 = new Composite(baseComposite, SWT.NONE);
contentComposite1.setLayout(new GridLayout());
contentComposite1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
final Label contentLabel1 = new Label(contentComposite1, SWT.NONE);
contentLabel1.setText("I stretch to fill available space!");
final Composite stackComposite = new Composite(baseComposite, SWT.NONE);
final StackLayout stackLayout = new StackLayout();
stackComposite.setLayout(stackLayout);
stackComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));
final Composite stackContentComposite = new Composite(stackComposite, SWT.NONE);
stackContentComposite.setLayout(new GridLayout());
stackContentComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
final Label stackContentLabel = new Label(stackContentComposite, SWT.NONE);
stackContentLabel.setText("I can disappear and reappear!");
stackLayout.topControl = stackContentComposite;
final Composite contentComposite3 = new Composite(baseComposite, SWT.NONE);
contentComposite3.setLayout(new GridLayout());
contentComposite3.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));
final Label contentLabel3 = new Label(contentComposite3, SWT.NONE);
contentLabel3.setText("I live on the end :(");
final Button flipButton = new Button(shell, SWT.PUSH);
flipButton.setText("Flip");
flipButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
if (stackLayout.topControl == null) {
stackLayout.topControl = stackContentComposite;
((GridData) stackComposite.getLayoutData()).exclude = false;
// ((GridLayout) baseComposite.getLayout()).numColumns++;
stackComposite.setVisible(true);
baseComposite.layout(true, true);
} else {
stackLayout.topControl = null;
((GridData) stackComposite.getLayoutData()).exclude = true;
// ((GridLayout) baseComposite.getLayout()).numColumns--;
stackComposite.setVisible(false);
baseComposite.layout(true, true);
}
}
});
}
public void run() {
shell.setSize(600, 115);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
public static void main(final String... args) {
new MCVE().run();
}
}
我想不出别的办法了。
选项 1 绝对是我会使用的并且被 Eclipse 代码广泛使用(例如对话框按钮栏上的按钮)。
由于您已经假设控件布局数据为 GridData
,因此可以安全地假设父布局为 GridLayout
(将 GridData
设置为某些其他布局上的布局数据通常会给一个运行时间错误)。
tl;dr 有没有一种好方法可以隐藏 GridLayout
中的列并隐藏父级 Composite
中剩余的列间距?
我在 GridLayout
中有一个包含多个列的组合。一列是一个 Composite
和一个 StackLayout
,这样我就可以 hide/show Composite
.
例如:
为了完成 hiding/showing,我一直在 GridData
上设置 exclude
属性,在 StackLayout
上设置 topControl
属性:
// To hide
stackLayout.topControl = null;
stackComposite.setVisible(false);
((GridData) stackComposite.getLayoutData()).exclude = true;
现在,当我隐藏中间 Composite
时,我看到额外的 space 出现在行的远端。
这大概是因为baseComposite
上的GridLayout
的列数还是一样的,所以我们看到的是一个宽度为0的列,两边指定的列间距.
为了解决这个问题,我提出了几个(不理想的)解决方案:
Decrement/increment时的列数hiding/showing.
我们不使用
exclude
属性,而是用StackLayout
覆盖Composite
并将computeSize(...)
函数更改为 return 0,或者根据我们是否希望它出现来计算实际大小。 (这是迄今为止我最不喜欢的选项,我什至觉得写它都很糟糕)将基础
Composite
上的horizontalSpacing
设置为 0,而不是使用每个列内的间距Composite
来指定间距。隐藏时看起来像这样:
选项 1 到目前为止是最吸引人的,但是在尝试保持代码模块化时这里有一个明显的缺点。例如,如果每个列的 Composite
由某个可重用组件设置,则 decrementing/incrementing 列计数取决于该组件知道其父 Composite
具有 GridLayout
- 不是一个安全的假设!
选项2我坚决不喜欢。
选项 3 并不可怕,但它仍然感觉像是对间距和边距的误用。另外,回到模块化的观点,其他列组件将负责影响更大视图的间距,而不是让更大的视图决定间距。
所以我的问题归结为:还有比这三个更好的选择吗?
MCVE 用于获取上图:
public class MCVE {
final Display display;
final Shell shell;
public MCVE() {
display = new Display();
shell = new Shell(display);
shell.setLayout(new GridLayout());
shell.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
final Composite baseComposite = new Composite(shell, SWT.NONE);
baseComposite.setLayout(new GridLayout(3, false));
baseComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
baseComposite.setBackground(new Color(display, new RGB(125, 125, 255)));
final Composite contentComposite1 = new Composite(baseComposite, SWT.NONE);
contentComposite1.setLayout(new GridLayout());
contentComposite1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
final Label contentLabel1 = new Label(contentComposite1, SWT.NONE);
contentLabel1.setText("I stretch to fill available space!");
final Composite stackComposite = new Composite(baseComposite, SWT.NONE);
final StackLayout stackLayout = new StackLayout();
stackComposite.setLayout(stackLayout);
stackComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));
final Composite stackContentComposite = new Composite(stackComposite, SWT.NONE);
stackContentComposite.setLayout(new GridLayout());
stackContentComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
final Label stackContentLabel = new Label(stackContentComposite, SWT.NONE);
stackContentLabel.setText("I can disappear and reappear!");
stackLayout.topControl = stackContentComposite;
final Composite contentComposite3 = new Composite(baseComposite, SWT.NONE);
contentComposite3.setLayout(new GridLayout());
contentComposite3.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));
final Label contentLabel3 = new Label(contentComposite3, SWT.NONE);
contentLabel3.setText("I live on the end :(");
final Button flipButton = new Button(shell, SWT.PUSH);
flipButton.setText("Flip");
flipButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
if (stackLayout.topControl == null) {
stackLayout.topControl = stackContentComposite;
((GridData) stackComposite.getLayoutData()).exclude = false;
// ((GridLayout) baseComposite.getLayout()).numColumns++;
stackComposite.setVisible(true);
baseComposite.layout(true, true);
} else {
stackLayout.topControl = null;
((GridData) stackComposite.getLayoutData()).exclude = true;
// ((GridLayout) baseComposite.getLayout()).numColumns--;
stackComposite.setVisible(false);
baseComposite.layout(true, true);
}
}
});
}
public void run() {
shell.setSize(600, 115);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
public static void main(final String... args) {
new MCVE().run();
}
}
我想不出别的办法了。
选项 1 绝对是我会使用的并且被 Eclipse 代码广泛使用(例如对话框按钮栏上的按钮)。
由于您已经假设控件布局数据为 GridData
,因此可以安全地假设父布局为 GridLayout
(将 GridData
设置为某些其他布局上的布局数据通常会给一个运行时间错误)。