如何过滤swt tableviewer中的超链接单元格

How to filter hyperlink cells in swt tableviewer

我有一个问题我无法解决,我花了很多时间。我有一个 table 和一个带有超链接的列。我在 table 中添加了一些过滤器,当我激活其中一个过滤器时,超链接列没有正确刷新。我实现的代码如上所示。这是您可以复制和粘贴的示例,运行 并重现错误:

Table class:

package borrar;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.widgets.Hyperlink;

public class Example {

    private static TableViewer tViewer = null;
    private static Table tblTrades = null;
    private static Text txtTicker;
    public static TickerFilter2 tickerFilter = new TickerFilter2();

    public static void main(String[] args) {

        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setLayout(new FillLayout());
        Composite parent = new Composite(shell, SWT.NONE);
        parent.setLayout(new FillLayout());
        parent.setLayout(new GridLayout(1, true));
        Label lblTicker = new Label(parent, SWT.NONE);
        lblTicker.setText("Search: ");
        txtTicker = new Text(parent, SWT.NONE);
        txtTicker.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
        txtTicker.addKeyListener(new KeyAdapter() {
            public void keyReleased(KeyEvent ke) {
                tickerFilter.setSearchText(txtTicker.getText());
                tViewer.refresh();
            }
        });
        tViewer = new TableViewer(parent, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION | SWT.CENTER);
        String[] titles = { "Ticker", "Hyperlinks" };
        createColumns(titles);
        tblTrades = tViewer.getTable();
        tViewer.setContentProvider(new ArrayContentProvider());
        List<DataTable> dt = Arrays.asList(new DataTable("AAA", "ImagePath"), new DataTable("ABBBBBB", "ImagePath"),
                new DataTable("BBBBBBB", "ImagePath"));
        tViewer.setInput(dt);
        tblTrades.setHeaderVisible(true);
        tViewer.addFilter(tickerFilter);

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

    private static void createColumns(String[] titles) {
        TableViewerColumn col = createTableViewerColumn(titles[0], 70);
        col.setLabelProvider(new ColumnLabelProvider() {
            @Override
            public String getText(Object element) {
                DataTable op = (DataTable) element;
                if (op.getTicker() != null) {
                    return op.getTicker();
                } else {
                    return "";
                }
            }
        });
        col = createTableViewerColumn(titles[1], 80);
        col.setLabelProvider(new ColumnLabelProvider() {
            Map<Object, Hyperlink> hyperlinks = new HashMap<Object, Hyperlink>();

            @Override
            public void update(ViewerCell cell) {
                TableItem item = (TableItem) cell.getItem();
                final Hyperlink hyperlink;
                if (hyperlinks.containsKey(cell.getElement()) && !hyperlinks.get(cell.getElement()).isDisposed()) {
                    hyperlink = hyperlinks.get(cell.getElement());
                } else {
                    hyperlink = new Hyperlink((Composite) (cell.getViewerRow().getControl()), SWT.NONE);
                    if (cell.getElement() instanceof DataTable) {
                        DataTable trade = (DataTable) cell.getElement();
                        if (trade.getPath() != null && !trade.getPath().equals("")) {
                            hyperlink.setText(trade.getPath() + "-" + trade.getTicker());
                            hyperlink.setHref(trade.getPath());
                        }
                    }
                    hyperlink.addHyperlinkListener(new HyperlinkAdapter() {
                        public void linkActivated(HyperlinkEvent e) {
                            org.eclipse.swt.program.Program.launch(hyperlink.getHref().toString());
                        }
                    });
                    hyperlinks.put(cell.getElement(), hyperlink);
                }
                TableEditor editor = new TableEditor(item.getParent());
                editor.grabHorizontal = true;
                editor.grabVertical = true;
                editor.setEditor(hyperlink, item, cell.getColumnIndex());
                editor.layout();
            }
        });
    }

    private static TableViewerColumn createTableViewerColumn(String title, int bound) {
        final TableViewerColumn viewerColumn = new TableViewerColumn(tViewer, SWT.CENTER);
        final TableColumn column = viewerColumn.getColumn();
        column.setText(title);
        column.setWidth(bound);
        column.setResizable(true);
        column.setMoveable(true);
        return viewerColumn;
    }

    public void refreshTable() {
        tViewer.refresh();
    }
}


我的过滤器class:

package borrar;

import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;

public class TickerFilter2 extends ViewerFilter {
    private String searchString;

    public void setSearchText(String s) {
        // ensure that the value can be used for matching
        this.searchString = ".*" + s + ".*";
    }

    @Override
    public boolean select(Viewer viewer, Object parentElement, Object element) {
        if (searchString == null || searchString.length() == 0) {
            return true;
        }
        DataTable trade = (DataTable) element;
        if (trade.getTicker().matches(searchString)) {
            return true;
        }
        return false;
    }

}

数据table对象:

package borrar;

public class DataTable {

    String ticker;
    String path;

    public DataTable(String ticker, String path) {
        super();
        this.ticker = ticker;
        this.path = path;
    }

    public String getTicker() {
        return ticker;
    }

    public void setTicker(String ticker) {
        this.ticker = ticker;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }
}

例如,如果您在搜索字段中输入“z”或“l”,您会看到超链接列没有过滤。

过滤器 class 正确过滤数据,但超链接列过滤不正确。

这是一张效果不佳的图片:

TableViewer 并不真正了解 TableEditor 代码,因此在过滤时不会处理它们。

您也许可以使用 EditingSupport 代码。以下代码定义了一个单元格编辑器,它会在您单击列单元格时立即执行操作。

对于列定义,将您的代码替换为:

   col.setLabelProvider(new ColumnLabelProvider() {
      @Override
      public String getText(final Object element) {
          // Whatever you want for the cell text here
          final DataTable op = (DataTable) element;
          return op.getPath();
       }
    });

    col.setEditingSupport(new HyperlinkEditingSupport(tViewer));

编辑支持class:

public class HyperlinkEditingSupport extends EditingSupport
{
  private final HyperlinkCellEditor _editor;

  public HyperlinkEditingSupport(final TableViewer viewer)
  {
    super(viewer);

    _editor = new HyperlinkCellEditor(viewer.getTable());
  }

  @Override
  protected CellEditor getCellEditor(final Object element)
  {
    return _editor;
  }

  @Override
  protected boolean canEdit(final Object element)
  {
    return true;
  }

  @Override
  protected Object getValue(final Object element)
  {
    // Return the value you want launched
    return ((DataTable)element).getPath();
  }

  @Override
  protected void setValue(final Object element, final Object value)
  {
    // no action
  }
}

CellEditor。这有点奇怪,因为我们将在调用编辑器后立即启动,所以我们真的不需要单独的编辑器:

public class HyperlinkCellEditor extends CellEditor
{
  public HyperlinkCellEditor(final Composite parent)
  {
    super(parent);
  }

  @Override
  protected Control createControl(final Composite parent)
  {
    return new Composite(parent, SWT.None);
  }

  @Override
  protected Object doGetValue()
  {
    return new Object[0];
  }

  @Override
  protected void doSetFocus()
  {
    // no action
  }

  @Override
  protected void doSetValue(final Object value)
  {
    final String path = (String)value;

    // TODO Open the link
  }
}

我修改了@greg-449 解决方案以在仅修改 LabelProvider 的单元格中显示 link 外观:

col.setLabelProvider(new StyledCellLabelProvider() {
        @Override
        public void update(ViewerCell cell) {
            DataTable op = (DataTable) cell.getItem().getData();
            StyledString ss = new StyledString();
            StyleRange sr = new StyleRange(0, 80, Display.getCurrent().getSystemColor(SWT.COLOR_BLUE), null);
            sr.underline = true;
            ss.append(op.getPath(), StyledString.DECORATIONS_STYLER);
            cell.setText("Open Image");
            StyleRange[] range = { sr };
            cell.setStyleRanges(range);
        }
    });
    col.setEditingSupport(new HyperlinkEditingSupport(tViewer));