简体   繁体   中英

How to always show vertical scroll bar in SWT table?

Is it possible to always show the vertical scroll bar in a SWT table even if the table is empty? By always showing a (possible disabled) vertical scroll bar one can avoid that the last column get partially hidden when the columns use ColumnWeightData for layouting.

I tried to initialize the table with SWT.V_SCROLL or to use table.getVerticalBar().setVisible(true) - both without success.

There is a method setAlwaysShowScrollBars in ScrollableComposite . What I am looking for is a similar method in Table .

UPDATE: I suppose that the scroll bars which are visible when the table contains enough data are not those scroll bars which Table inherits from Scrollable . I have debugged ScrollBar.setVisible(boolean) and it seems not be called on table layout updates. Is this observation correct?

UPDATE 2: Here is a snippet for a table construction. It would be great to have the vertical scrollbar visible even if the table is empty and to have the column headers visible even if the table data are scrolled down. Note: The snippet has left out some details as the label provider and some other controls arranged at the same parent composite.

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");
}

It's not possible to force the Table to always show scroll bars, the OS decides when to show them.

Alternatives

Right, I came up with a solution very similar to my answer to this question:

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


The idea is to use a ScrolledComposite (as the other answer already suggested) to take care of the scrolling. The Table itself won't scroll. However , this won't make any difference, because the user won't be able to tell the difference.

ScrolledComposite has a method called setAlwaysShowScrollBars(boolean) with which you can force it to always show the scroll bars, even if they aren't required.

Here is some sample code, that will illustrate what I just talked about:

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();
}

Looks like this:

在此处输入图片说明在此处输入图片说明

As you can see, the scroll bar is always visible.


UPDATE

As pointed out in the comment, this approach will not keep the Table headers visible when you scroll down. If you could post a small working code example that illustrates your problem, we might come up with an alternative (unrelated to forcing the scroll bars).

UPDATE2

Here is some code that should do what you want, the trick is to trigger a resize event on the parent of the TableViewer , the horizontal scrollbar that is shown isn't really necessary and it disappears after you resize the window:

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;
    }
}

I have created a solution that I think is better than put your table inside a ScrolledComposite.

My solution: fill my table with empty items until my scroll bar is visible.

Example:

// 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 );

I hope this solution helps someone.

Thanks.

我认为您无法执行此操作,但是可以尝试将ScrolledComposite.setAlwaysShowScrollbars()调用为true,但是您将始终看到两个已启用的滚动条。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM