【问题标题】:How to always show vertical scroll bar in SWT table?如何始终在 SWT 表中显示垂直滚动条?
【发布时间】:2013-10-23 09:59:39
【问题描述】:

即使表是空的,是否可以始终在 SWT 表中显示垂直滚动条?通过始终显示(可能禁用)垂直滚动条,可以避免当列使用 ColumnWeightData 进行布局时,最后一列被部分隐藏。

我尝试使用 SWT.V_SCROLL 或使用 table.getVerticalBar().setVisible(true) 初始化表 - 均未成功。

ScrollableComposite 中有一个方法setAlwaysShowScrollBars。我正在寻找的是Table 中的类似方法。

更新:我想当表格包含足够数据时可见的滚动条不是TableScrollable继承的那些滚动条。我已经调试了ScrollBar.setVisible(boolean),它似乎没有在表格布局更新时被调用。这个观察正确吗?

更新 2: 这是用于表构造的 sn-p。即使表格是空的,垂直滚动条也可见,即使表格数据向下滚动,列标题也可见。注意:sn-p 省略了一些细节作为标签提供者和一些其他控件排列在同一个父组合中。

protected void createMasterPart(final IManagedForm managedForm, Composite parentComposite)
{
  FormToolkit toolkit = managedForm.getToolkit();

  Composite contentComposite = toolkit.createComposite(parentComposite, SWT.NONE);
  contentComposite.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1));
  toolkit.paintBordersFor(contentComposite);

  contentComposite.setLayout(new GridLayout(2, false));
  GridData gd;

  Composite tableComposite = new Composite(contentComposite, SWT.NONE);
  TableColumnLayout tableColumnLayout = new TableColumnLayout();
  tableComposite.setLayout(tableColumnLayout);
  gd = new GridData(SWT.FILL, SWT.FILL, true, false, 1, 3);
  tableComposite.setLayoutData(gd);

  speakerTableViewer = new TableViewer(tableComposite, SWT.BORDER | SWT.FULL_SELECTION);
  speakerTableViewer.setContentProvider(ArrayContentProvider.getInstance());
  Table speakerTable = speakerTableViewer.getTable();
  speakerTable.setHeaderVisible(true);
  speakerTable.setLinesVisible(true);
  toolkit.paintBordersFor(speakerTable);

  TableViewerColumn tableViewerAudiosampleColumn = new TableViewerColumn(speakerTableViewer, SWT.NONE);
  TableColumn audiosampleColumn = tableViewerAudiosampleColumn.getColumn();
  tableColumnLayout.setColumnData(audiosampleColumn, new ColumnWeightData(60, true));
  audiosampleColumn.setText("Sample");

  TableViewerColumn tableViewerSpeakerColumn = new TableViewerColumn(speakerTableViewer, SWT.NONE);
  TableColumn speakerColumn = tableViewerSpeakerColumn.getColumn();
  tableColumnLayout.setColumnData(speakerColumn, new ColumnWeightData(60, true));
  speakerColumn.setText("Speaker");

  TableViewerColumn tableViewerRemarkColumn = new TableViewerColumn(speakerTableViewer, SWT.NONE);
  TableColumn remarkColumn = tableViewerRemarkColumn.getColumn();
  tableColumnLayout.setColumnData(remarkColumn, new ColumnWeightData(120, true));
  remarkColumn.setText("Remark");
}

【问题讨论】:

  • 将表格包裹在面板内。
  • @Makky panel 是什么意思?
  • 为什么要为空数据表显示滚动条?
  • 您可以使用org.eclipse.jface.layout.TableColumnLayout,它会在出现滚动条时调整列大小。
  • @Makky 如果起初表格没有滚动条,后来出现滚动条,我想避免最后一列被部分隐藏。此外,我想避免在这种情况下调整列的大小。

标签: java swt tableview jface


【解决方案1】:

我认为你不能这样做,但你可以尝试将 ScrolledComposite.setAlwaysShowScrollbars() 调用为 true,但你会一直看到两个启用的滚动条。

【讨论】:

  • 该表不是ScrollableComposite 并且不在ScrollableComposite 内。 ScrolledComposite 是什么?
【解决方案2】:

无法强制Table 始终显示滚动条,由操作系统决定何时显示。

替代品

好吧,我想出了一个与我对这个问题的回答非常相似的解决方案:

Is it possible to get the vertical/horizontal scroll bar visible when the SWT List is in disabled state?


这个想法是使用ScrolledComposite(正如已经建议的其他答案)来处理滚动。 Table 本身不会滚动。 但是,这不会有任何区别,因为用户无法分辨出区别。

ScrolledComposite 有一个名为setAlwaysShowScrollBars(boolean) 的方法,您可以使用它强制它始终显示滚动条,即使它们不是必需的。

这里有一些示例代码,可以说明我刚才所说的内容:

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

    final ScrolledComposite composite = new ScrolledComposite(shell, SWT.V_SCROLL);
    composite.setLayout(new GridLayout());
    composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

    final Table table = new Table(composite, SWT.NO_SCROLL | SWT.FULL_SELECTION);
    table.setHeaderVisible(true);

    composite.setContent(table);
    composite.setExpandHorizontal(true);
    composite.setExpandVertical(true);
    composite.setAlwaysShowScrollBars(true);
    composite.setMinSize(table.computeSize(SWT.DEFAULT, SWT.DEFAULT));

    Button fillTable = new Button(shell, SWT.PUSH);
    fillTable.setText("Fill table");
    fillTable.setLayoutData(new GridData(SWT.FILL, SWT.END, true, false));

    fillTable.addListener(SWT.Selection, new Listener()
    {
        @Override
        public void handleEvent(Event arg0)
        {
            if (table.getColumnCount() < 1)
            {
                for (int col = 0; col < 4; col++)
                {
                    TableColumn column = new TableColumn(table, SWT.NONE);
                    column.setText("Column " + col);
                }
            }

            for (int row = 0; row < 20; row++)
            {
                TableItem item = new TableItem(table, SWT.NONE);

                for (int col = 0; col < table.getColumnCount(); col++)
                {
                    item.setText(col, "Item " + row + " " + col);
                }
            }

            for (int col = 0; col < table.getColumnCount(); col++)
            {
                table.getColumn(col).pack();
            }

            composite.setMinSize(table.computeSize(SWT.DEFAULT, SWT.DEFAULT));
        }
    });

    Button clearTable = new Button(shell, SWT.PUSH);
    clearTable.setText("Clear table");
    clearTable.setLayoutData(new GridData(SWT.FILL, SWT.END, true, false));

    clearTable.addListener(SWT.Selection, new Listener()
    {
        @Override
        public void handleEvent(Event arg0)
        {
            table.removeAll();

            composite.setMinSize(table.computeSize(SWT.DEFAULT, SWT.DEFAULT));
        }
    });

    shell.pack();
    shell.setSize(400, 300);
    shell.open();
    while (!shell.isDisposed())
    {
        if (!display.readAndDispatch())
            display.sleep();
    }
    display.dispose();
}

看起来像这样:

如您所见,滚动条始终可见。


更新

正如评论中所指出的,当您向下滚动时,这种方法不会保持 Table 标题可见。如果您可以发布一个小的工作代码示例来说明您的问题,我们可能会提出一个替代方案(与强制滚动条无关)。

更新2

这里有一些代码应该做你想做的事,诀窍是在TableViewer 的父级上触发调整大小事件,显示的水平滚动条并不是真正必要的,它会在你调整窗口大小后消失:

public static void main(String[] args)
{
    final Display display = new Display();
    final Shell shell = new Shell(display);
    shell.setText("StackOverflow");
    shell.setLayout(new GridLayout());

    createMasterPart(shell);

    shell.pack();
    shell.setSize(400, 300);
    shell.open();

    shell.layout(true, true);

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

private static void createMasterPart(Composite parentComposite)
{
    Composite composite = new Composite(parentComposite, SWT.NONE);
    composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    composite.setLayout(new GridLayout(1, false));

    Composite tableComposite = new Composite(composite, SWT.NONE);
    TableColumnLayout tableColumnLayout = new TableColumnLayout();
    tableComposite.setLayout(tableColumnLayout);
    tableComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

    TableViewer tableViewer = new TableViewer(tableComposite, SWT.BORDER | SWT.FULL_SELECTION);
    tableViewer.setContentProvider(ArrayContentProvider.getInstance());
    Table table = tableViewer.getTable();
    table.setHeaderVisible(true);
    table.setLinesVisible(true);

    TableViewerColumn firstTableViewerColumn = new TableViewerColumn(tableViewer, SWT.NONE);
    TableColumn firstTableColumn = firstTableViewerColumn.getColumn();
    firstTableColumn.setText("Sample");
    firstTableViewerColumn.setLabelProvider(new ColumnLabelProvider()
    {
        @Override
        public String getText(Object element)
        {
            Dummy p = (Dummy) element;
            return p.first;
        }
    });

    TableViewerColumn secondTableViewerColumn = new TableViewerColumn(tableViewer, SWT.NONE);
    TableColumn secondTableColumn = secondTableViewerColumn.getColumn();
    secondTableColumn.setText("Speaker");
    secondTableViewerColumn.setLabelProvider(new ColumnLabelProvider()
    {
        @Override
        public String getText(Object element)
        {
            Dummy p = (Dummy) element;
            return p.second;
        }
    });

    TableViewerColumn thirdTableViewerColumn = new TableViewerColumn(tableViewer, SWT.NONE);
    TableColumn thirdTableColumn = thirdTableViewerColumn.getColumn();
    thirdTableColumn.setText("Remark");
    thirdTableViewerColumn.setLabelProvider(new ColumnLabelProvider()
    {
        @Override
        public String getText(Object element)
        {
            Dummy p = (Dummy) element;
            return p.third;
        }
    });

    List<Dummy> elements = new ArrayList<>();

    for(int i = 0; i < 20; i++)
    {
        elements.add(new Dummy("firstfirstfirst " + i, "secondsecondsecond " + i, "thirdthirdthirdthirdthirdthird " + i));
    }

    tableViewer.setInput(elements);

    tableColumnLayout.setColumnData(firstTableColumn, new ColumnWeightData(1, true));
    tableColumnLayout.setColumnData(secondTableColumn, new ColumnWeightData(1, true));
    tableColumnLayout.setColumnData(thirdTableColumn, new ColumnWeightData(2, true));
}

private static class Dummy
{
    public String first;
    public String second;
    public String third;

    public Dummy(String first, String second, String third)
    {
        this.first = first;
        this.second = second;
        this.third = third;
    }
}

【讨论】:

  • 向下滚动后列标题是否仍然可见?
  • @Basilevs 他们从来不在 SWT Tables。
  • 通常表格标题总是显示在每个滚动位置。
  • @Basilevs Huh,从未意识到。他们绝对不会使用此代码。 OP 必须决定什么更重要。
  • @Baz 感谢您的帮助!但是,表头对我来说更重要(作为问题所有者)。是的:问题似乎出在操作系统上。如何强制操作系统显示滚动条?有没有办法在表格对象上设置属性组合,让操作系统显示滚动条?
【解决方案3】:

我创建了一个我认为比将表格放在 ScrolledComposite 中更好的解决方案。

我的解决方案:用空项目填充我的表格,直到我的滚动条可见。

例子:

// Flag that knows if the empty item was added or not
boolean addedEmptyItem = false;

// Get the table client area
Rectangle rect = table.getClientArea ();
// Get the item height 
int itemHeight = table.getItemHeight ();
// Get the header height
int headerHeight = table.getHeaderHeight ();
// Calculate how many items can be visible without scrolling
int visibleCount = (rect.height - headerHeight + itemHeight - 1) / itemHeight;

while ( visibleCount > table.getItemCount() ) {
   // Add an empty item
   new TableItem( table, SWT.NONE );

   // Set the flag
   addedEmptyItem = true;
}

// Vertical bar é disabled if an empty item was added
table.getVerticalBar().setEnabled( !addedEmptyItem );

我希望这个解决方案对某人有所帮助。

谢谢。

【讨论】:

  • 感谢您的示例!但是,恐怕要让这个 hack 在生产环境中发挥作用还有很多工作要做:禁用选择空项目;调整表格大小时进行调整;如果添加了真实物品,则进行调整;使用表格模型。还是谢谢!
猜你喜欢
  • 1970-01-01
  • 2011-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-07
  • 1970-01-01
相关资源
最近更新 更多