SWT分段表&滚动

时间:2012-03-24 20:06:41

标签: java eclipse-plugin swt

我正在尝试在表单部分中显示SWT表,但是在列调整大小和滚动时出现问题。

我附上了一些示例代码,可以放在Eclipse插件的ViewPart中(3.7是我正在使用的版本)。如果您运行代码,并将列调整到右侧,则表格会获得一个水平滚动条(这就是我想要的)。

现在,如果我折叠该部分(单击“Section Title”左侧的箭头),视图将获得一个水平滚动条(我不想要)。再次展开该部分,视图滚动仍然存在,现在该表不再有一个。

我正在寻找一种方法(可能是嵌套复合材料的一些可怕组合)来阻止桌子比视图宽,并且会欣赏任何建议。

public class ExampleView extends ViewPart {
  /** Note: other fields / methods removed to condense snippet */

  private FormToolkit toolkit;
  private ScrolledForm scrolledForm;

  public void createPartControl(Composite parent) {
            parent.setLayout(new FillLayout());

    toolkit = new FormToolkit(parent.getDisplay());
    scrolledForm = toolkit.createScrolledForm(parent);
    scrolledForm.setExpandHorizontal(true);
    scrolledForm.setText("Form Title");

    scrolledForm.getBody().setLayout(new FillLayout());
    // here's the modification for the solution
    scrolledForm.getBody().setLayout(
            new BoundedLayout(new FillLayout(), true));

    final Section section = toolkit.createSection(scrolledForm.getBody(),
            Section.DESCRIPTION | Section.TITLE_BAR | Section.TWISTIE
                    | Section.EXPANDED);

    section.addExpansionListener(new ExpansionAdapter() {
        public void expansionStateChanged(ExpansionEvent e) {
            scrolledForm.reflow(true);
        }
    });
    section.setText("Section Title");

    final Table table = toolkit.createTable(section, SWT.FULL_SELECTION);
    TableViewer viewer = new TableViewer(table);

    table.setLinesVisible(true);
    table.setHeaderVisible(true);
    table.setItemCount(10);

    TableColumn col = new TableColumn(table, SWT.NONE);
    col.setText("Column A");
    col.setWidth(150);
    col.setResizable(true);
    col.setMoveable(true);

    TableColumn col2 = new TableColumn(table, SWT.NONE);
    col2.setText("Column B");
    col2.setWidth(150);
    col2.setResizable(true);
    col2.setMoveable(true);

    section.setClient(table);
  }
}

2 个答案:

答案 0 :(得分:1)

所以这是我使用自定义布局提出的解决方案。它包装了另一个布局,但是可以将computeSize绑定到父组合的宽度或高度 - 基本上只允许在一个方向上滚动(如果有更简单的方法强制ScrolledForm执行此操作请让我知道!)。

由于computeSizelayout方法为protected

,因此需要应用一些令人讨厌的反思黑客攻击
import java.lang.reflect.Method;

import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Layout;

public class BoundedLayout extends Layout {
  protected Layout delegateLayout;

  protected Method computeSizeMethod;
  protected Method layoutMethod;

  protected boolean widthBound;

  public BoundedLayout(Layout delegateLayout, boolean widthBound) {
      setDelegateLayout(delegateLayout);
      this.widthBound = widthBound;
  }

  public Layout getDelegateLayout() {
      return delegateLayout;
  }

  public void setDelegateLayout(Layout delegateLayout) {
      this.delegateLayout = delegateLayout;

      try {
          computeSizeMethod = delegateLayout.getClass().getDeclaredMethod(
                "computeSize", Composite.class, int.class, int.class,
                boolean.class);
          computeSizeMethod.setAccessible(true);

          layoutMethod = delegateLayout.getClass().getDeclaredMethod(
                "layout", Composite.class, boolean.class);
          layoutMethod.setAccessible(true);
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
  }

  @Override
  protected Point computeSize(Composite composite, int wHint, int hHint,
        boolean flushCache) {
    // get comp size to make sure we don't let any children exceed it
    Point compSize = composite.getSize();

    try {
        Point layoutComputedSize = (Point) computeSizeMethod.invoke(
                delegateLayout, composite, wHint, hHint, flushCache);

        if (widthBound) {
            layoutComputedSize.x = Math.min(compSize.x,
                    layoutComputedSize.x);
        } else {
            layoutComputedSize.y = Math.min(compSize.y,
                    layoutComputedSize.y);
        }

        return layoutComputedSize;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
  }

  @Override
  protected void layout(Composite composite, boolean flushCache) {
    try {
        layoutMethod.invoke(delegateLayout, composite, flushCache);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
  }
}

答案 1 :(得分:0)

如果将Section.COMPACT样式添加到Section中,则该部分的宽度将仅在展开状态下调整大小。在折叠状态下,它将恢复正常大小。

如果您不希望再次展开后该部分的宽度增加,我认为您必须在ExpansionAdapter中使用变通方法。折叠时手动存储宽度,并在展开时将其设置回来。

顺便说一句,我建议使用WindowBuilder来构建GUI,以便更容易调整和移动内容。