2012-01-23 111 views
5

我开发Eclipse RCP应用程序,并遇到Table的问题。我们在布尔格式数据库中有一些数据,用户希望使用checkbox来查看该字段。如何将图像与表格单元格的中心对齐(SWT表格)

我尝试使用Button(SWT.CHECK)作为表编辑器来实现它,但它的工作速度太慢:(

我试图用2个图像 - 选中和未选中的复选框,它的工作原理,但我可以” t我们甚至发现如何捕捉SWT.MeasureItemSWT.PaintItem事件,并通过更改event.x字段手动处理它们,但是我遇到了一个问题 - 我无法得到列测量结果或绘画,因为事件不会提供给我这些信息。

是否通过修改重绘时的事件数据将图像对齐到中心的唯一方法,或者可能有其他方法通过复选框表示布尔数据?我现在不需要编辑它们,所以只读模式应该足够了。

+0

我有些震惊,让操作系统绘制复选框比绘制自己的图像慢。 –

+0

@EdwardThomson我认为这真的取决于实施.. – Sorceror

回答

8

您可以添加PaintListener你的表以及何时会画画(在我的情况下,5列)选择的列,检查行的大小和自己定位的图像..

testTable.addListener(SWT.PaintItem, new Listener() { 

    @Override 
    public void handleEvent(Event event) { 
     // Am I on collumn I need..? 
     if(event.index == 5) { 
      Image tmpImage = IMAGE_TEST_PASS; 
      int tmpWidth = 0; 
      int tmpHeight = 0; 
      int tmpX = 0; 
      int tmpY = 0; 

      tmpWidth = testTable.getColumn(event.index).getWidth(); 
      tmpHeight = ((TableItem)event.item).getBounds().height; 

      tmpX = tmpImage.getBounds().width; 
      tmpX = (tmpWidth/2 - tmpX/2); 
      tmpY = tmpImage.getBounds().height; 
      tmpY = (tmpHeight/2 - tmpY/2); 
      if(tmpX <= 0) tmpX = event.x; 
      else tmpX += event.x; 
      if(tmpY <= 0) tmpY = event.y; 
      else tmpY += event.y; 
      event.gc.drawImage(tmpImage, tmpX, tmpY); 
     } 
    } 
}); 
2

下面是使用OwnerDrawLabelProvider的例子:http://bingjava.appspot.com/snippet.jsp?id=3221

我与东铭的链接合并成为TableViewers and Nativelooking Checkboxes,创造便利的抽象类CenteredCheckboxLabelProvider

import org.eclipse.jface.resource.JFaceResources; 
import org.eclipse.jface.viewers.ColumnViewer; 
import org.eclipse.jface.viewers.OwnerDrawLabelProvider; 
import org.eclipse.swt.SWT; 
import org.eclipse.swt.graphics.GC; 
import org.eclipse.swt.graphics.Image; 
import org.eclipse.swt.graphics.Point; 
import org.eclipse.swt.graphics.Rectangle; 
import org.eclipse.swt.widgets.Button; 
import org.eclipse.swt.widgets.Event; 
import org.eclipse.swt.widgets.Shell; 
import org.eclipse.swt.widgets.TableItem; 

public abstract class CenteredCheckboxLabelProvider extends OwnerDrawLabelProvider { 
    private static final String CHECKED_KEY = "CHECKED"; 
    private static final String UNCHECK_KEY = "UNCHECKED"; 

    public CenteredCheckboxLabelProvider(ColumnViewer viewer) { 
     if (JFaceResources.getImageRegistry().getDescriptor(CHECKED_KEY) == null) { 
      JFaceResources.getImageRegistry().put(UNCHECK_KEY, makeShot(viewer.getControl().getShell(), false)); 
      JFaceResources.getImageRegistry().put(CHECKED_KEY, makeShot(viewer.getControl().getShell(), true)); 
     } 
    } 

    private Image makeShot(Shell shell, boolean type) { 
     Shell s = new Shell(shell, SWT.NO_TRIM); 
     Button b = new Button(s, SWT.CHECK); 
     b.setSelection(type); 
     Point bsize = b.computeSize(SWT.DEFAULT, SWT.DEFAULT); 
     b.setSize(bsize); 
     b.setLocation(0, 0); 
     s.setSize(bsize); 
     s.open(); 

     GC gc = new GC(b); 
     Image image = new Image(shell.getDisplay(), bsize.x, bsize.y); 
     gc.copyArea(image, 0, 0); 
     gc.dispose(); 

     s.close(); 

     return image; 
    } 

    public Image getImage(Object element) { 
     if (isChecked(element)) { 
      return JFaceResources.getImageRegistry().get(CHECKED_KEY); 
     } else { 
      return JFaceResources.getImageRegistry().get(UNCHECK_KEY); 
     } 
    } 

    @Override 
    protected void measure(Event event, Object element) { 
    } 

    @Override 
    protected void paint(Event event, Object element) { 
     Image img = getImage(element); 

     if (img != null) { 
      Rectangle bounds = ((TableItem) event.item).getBounds(event.index); 
      Rectangle imgBounds = img.getBounds(); 
      bounds.width /= 2; 
      bounds.width -= imgBounds.width/2; 
      bounds.height /= 2; 
      bounds.height -= imgBounds.height/2; 

      int x = bounds.width > 0 ? bounds.x + bounds.width : bounds.x; 
      int y = bounds.height > 0 ? bounds.y + bounds.height : bounds.y; 

      event.gc.drawImage(img, x, y); 
     } 
    } 

    protected abstract boolean isChecked(Object element); 
} 
+0

光荣,非常感谢! 我只需要做一点改变:我使用了TreeViewer,所以事件中的项目是TreeItem而不是TableItem;我只是使用instanceof来处理这两种情况。 –

+0

哎哟,我说的太快了......选择状态的背景颜色有问题,它与同一行的所有其他单元不同,并且看起来很丑。我已经尝试了很多东西,但一直无法解决它。 -_-我也结束了使用Sorceror的解决方案。 –

0

魔法师的解决方案就派上了用场。我已经适应它的自定义IStyledLabelProvider要在DelegatingStyledCellLabelProvider内使用:

public class MutedLabelProvider extends LabelProvider implements IStyledLabelProvider { 

    public MutedLabelProvider(Tree containerTree, int columnIndex) { 
    registerIconListener(containerTree, columnIndex); 
    } 

    @Override 
    public StyledString getStyledText(Object element) { 
    return new StyledString(); 
    } 

    private void registerIconListener(Tree containerTree, int columnIndex) { 
    containerTree.addListener(SWT.PaintItem, new Listener() { 
     @Override 
     public void handleEvent(Event event) { 
     if (event.index == columnIndex) { 
      TreeItem treeItem = (TreeItem) event.item; 
      Object data = treeItem.getData(); 
      Image tmpImage = getImageFromData(data); 
      if (tmpImage != null) { 
      int tmpWidth = 0; 
      int tmpHeight = 0; 
      int tmpX = 0; 
      int tmpY = 0; 
      tmpWidth = containerTree.getColumn(event.index).getWidth(); 
      tmpHeight = treeItem.getBounds().height; 
      tmpX = tmpImage.getBounds().width; 
      tmpX = (tmpWidth/2 - tmpX/2); 
      tmpY = tmpImage.getBounds().height; 
      tmpY = (tmpHeight/2 - tmpY/2); 
      if (tmpX <= 0) tmpX = event.x; 
      else tmpX += event.x; 
      if (tmpY <= 0) tmpY = event.y; 
      else tmpY += event.y; 
      event.gc.drawImage(tmpImage, tmpX, tmpY); 
      } 
     } 
     } 
    }); 
    } 

    private Image getImageFromData(Object element) { 
    if (element != null && element instanceof IMarker) { 
     IMarker marker = (IMarker) element; 
     boolean isItTrue = marker.getAttribute("MyBooleanAttr", false); 
     if (isItTrue) { 
     // TODO return here the image you want for true state 
     return JFaceResources.getImageRegistry().get("MyImageForTrue"); 
     } else { 
     // TODO return here the image you want for false state 
     // Alternatively, you can return null for no image 
     return null; 
     } 
    } else { 
     return null; 
    } 
    } 

} 

请注意,我用IMarker作为元素的数据,和TreeViewer中(所以我收到TreeItems),但您的数据可能会有所不同,并且您的查看器可能是TableViewer;你只需要做出自己的调整。