Eclipse status trimbar贡献内容动态变化时宽度自适应实现问题
Eclipse状态栏自定义贡献项动态宽度适配方案
需求说明
开发Eclipse status trimbar自定义贡献项,要求贡献项内部子元素文本动态变化时宽度可自动适配内容,类似VSCode状态栏的动态宽度效果。如果自适应宽度实现难度较高,也可接受状态栏贡献项固定宽度、或者每个子元素单独设置固定宽度的方案,无动态增减子元素的需求。
运行环境:Linux系统下Eclipse 2021-06 (4.20.0)版本
现有实现基础
plugin.xml扩展注册
<extension point="org.eclipse.ui.menus"> <menuContribution locationURI="toolbar:org.eclipse.ui.trim.status"> <toolbar id="some.package.StatusTrimBarContribution"> <control class="some.package.StatusTrimBarContribution"> </control> </toolbar> </menuContribution> </extension>
基础贡献类代码
public class StatusTrimBarContribution extends WorkbenchWindowControlContribution { private static String currText = "empty"; private Label m_lbl = null; private Label m_lbl2 = null; private Composite m_root = null; public StatusTrimBarContribution() { // 注册字符串更新事件 } @Override public void dispose() { // 注销字符串更新事件 } @Override protected Control createControl(Composite parent) { // 布局实现见下方方案 } @Subscribe // 来自guava事件总线 private void someEventHandler(String event) { currText = "lp_much_longer"; if (m_lbl != null && !m_lbl.isDisposed()) { m_lbl.setText(currText); // 布局刷新逻辑见下方方案 } } }
已尝试的失败方案
方案1:带中间Composite的固定宽度GridLayout
在标签和父容器之间添加中间Composite,使用GridLayout布局,给m_lbl设置GridData固定宽200px,结果标签高度过高被截断,即便将布局边距高度设为0仍存在截断问题。
@Override protected Control createControl(Composite parent) { GridLayout gl = new GridLayout(2, false); Composite comp = new Composite(parent, SWT.NONE); comp.setLayout(gl); m_lbl = new Label(comp, SWT.RIGHT); m_lbl.setText(currText); GridDataFactory.defaultsFor(m_lbl).hint(200, SWT.DEFAULT).applyTo(m_lbl); m_lbl2 = new Label(comp, SWT.RIGHT); m_lbl2.setText("lbl2"); m_root = comp; return comp; }
方案2:直接在父容器使用GridLayout
移除中间Composite,直接给父容器设置GridLayout,删除GridData配置,结果和方案1一致,且m_lbl宽度不足以容纳文本内容。
@Override protected Control createControl(Composite parent) { GridLayout gl = new GridLayout(2, false); parent.setLayout(gl); m_lbl = new Label(parent, SWT.RIGHT); m_lbl.setText(currText); m_lbl2 = new Label(parent, SWT.RIGHT); m_lbl2.setText("lbl2"); m_root = new Composite(parent, SWT.NONE); return m_lbl; }
方案3:无布局直接创建标签
移除所有布局配置,直接在父容器创建标签,标签高度截断问题解决,但宽度仍不足以容纳文本。
@Override protected Control createControl(Composite parent) { m_lbl = new Label(parent, SWT.RIGHT); m_lbl.setText(currText); m_lbl2 = new Label(parent, SWT.RIGHT); m_lbl2.setText("lbl2"); m_root = new Composite(parent, SWT.NONE); return m_lbl; }
方案4:空白字符串预留宽度
初始化时给m_lbl设置长度为60的空白字符串预留宽度,结果两个标签都可以完整展示,但m_lbl2宽度和m_lbl一致远超需求,且不同用户字体差异会导致预留宽度适配性差。
// 初始化代码 private static String currText = " ".repeat(60); @Override protected Control createControl(Composite parent) { m_lbl = new Label(parent, SWT.RIGHT); m_lbl.setText(currText); m_lbl2 = new Label(parent, SWT.RIGHT); m_lbl2.setText("lbl2"); m_root = new Composite(parent, SWT.NONE); return m_lbl; }
可行实现方案
方案一:自适应宽度(推荐,匹配VSCode效果)
核心修正点:
- 保留中间Composite作为根容器,清空GridLayout的所有默认边距和间距,解决高度截断问题
- 给Label配置自适应内容的GridData,不写死宽度
- 文本更新后先调用根容器
pack()重算自身尺寸,再触发上层布局刷新
完整实现代码:
@Override protected Control createControl(Composite parent) { GridLayout gl = new GridLayout(2, false); // 清空所有默认边距和间距,解决高度截断问题 gl.marginWidth = 0; gl.marginHeight = 0; gl.horizontalSpacing = 4; // 两个标签之间可保留少量间距,按需调整 gl.verticalSpacing = 0; m_root = new Composite(parent, SWT.NONE); m_root.setLayout(gl); m_lbl = new Label(m_root, SWT.RIGHT); m_lbl.setText(currText); // 配置GridData:水平填充、垂直居中,自适应内容宽度 GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(false, false).applyTo(m_lbl); m_lbl2 = new Label(m_root, SWT.RIGHT); m_lbl2.setText("lbl2"); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(false, false).applyTo(m_lbl2); return m_root; } @Subscribe private void someEventHandler(String event) { currText = "lp_much_longer"; if (m_lbl != null && !m_lbl.isDisposed()) { m_lbl.setText(currText); // 先重算根容器尺寸 m_root.pack(); // 触发上层布局完整刷新 m_root.getParent().layout(true, true); m_root.getParent().getParent().requestLayout(); } }
方案二:子元素单独固定宽度(备选)
如果自适应宽度存在兼容问题,可给每个标签单独设置固定宽度,适配性优于全局预留空白:
@Override protected Control createControl(Composite parent) { GridLayout gl = new GridLayout(2, false); gl.marginWidth = 0; gl.marginHeight = 0; gl.horizontalSpacing = 4; gl.verticalSpacing = 0; m_root = new Composite(parent, SWT.NONE); m_root.setLayout(gl); m_lbl = new Label(m_root, SWT.RIGHT); m_lbl.setText(currText); // 单独给第一个标签设置固定宽度150px,按需调整 GridDataFactory.defaultsFor(m_lbl).hint(150, SWT.DEFAULT).applyTo(m_lbl); m_lbl2 = new Label(m_root, SWT.RIGHT); m_lbl2.setText("lbl2"); // 单独给第二个标签设置固定宽度50px,按需调整 GridDataFactory.defaultsFor(m_lbl2).hint(50, SWT.DEFAULT).applyTo(m_lbl2); return m_root; } @Subscribe private void someEventHandler(String event) { currText = "lp_much_longer"; if (m_lbl != null && !m_lbl.isDisposed()) { m_lbl.setText(currText); // 固定宽度方案不需要刷新布局,直接更新文本即可 } }
内容的提问来源于stack exchange,提问作者adentinger
相关产品推荐
相关产品推荐

