2012-01-23 17 views
5

Desarrollo la aplicación Eclipse RCP y tengo un problema con un Table. Tenemos algunos datos en la base de datos en formato booleano y los usuarios quieren ver ese campo usando checkbox.Cómo alinear la imagen al centro de la celda de la tabla (Tabla SWT)

Traté de hacerlo operativo Button(SWT.CHECK) como Tabla-Editor, pero funcionó demasiado lento :(

He intentado utilizar imágenes 2 - comprueban y casillas sin marcar, funciona, pero puedo' t ellos se alinean con el centro, que están alineados a la izquierda de forma automática

incluso encontré cómo atrapar SWT.MeasureItem y SWT.PaintItem eventos y procesar de forma manual por el campo event.x cambio, pero tengo un problema -. no puedo conseguir lo que la columna de medición o pintando en este momento, porque Event no me proporciona esa información.

¿Es la única manera de alinear las imágenes al centro modificando los datos del evento al volver a dibujar, o puede haber otras maneras de representar datos booleanos mediante casillas de verificación? No necesito editarlos ahora, por lo que el modo de solo lectura debería ser suficiente.

+0

Estoy sorprendido de que dejar que el sistema operativo dibuje casillas sea más lento que dibujar tus propias imágenes. –

+0

@EdwardThomson Creo que realmente depende de la implementación .. – Sorceror

Respuesta

8

Puede añadir PaintListener a su mesa y cuando se va a pintar la columna seleccionada (columna 5 en mi caso), comprobar el tamaño de la fila y alinear la imagen por sí mismo ..

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

Aquí está el ejemplo usando OwnerDrawLabelProvider: http://bingjava.appspot.com/snippet.jsp?id=3221

combiné con timonería de Tonny a TableViewers and Nativelooking Checkboxes y creé útil CenteredCheckboxLabelProvider clase abstracta

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

¡Glorioso, muchas gracias! Solo tuve que hacer un pequeño cambio: estoy usando un TreeViewer, por lo que los elementos en los eventos son TreeItem en lugar de TableItem; Acabo de utilizar instanceof para que funcione con ambos casos. –

+0

Ouch, hablé demasiado pronto ... Tenía problemas con el color de fondo del estado seleccionado, era diferente de todas las otras celdas de la misma fila, y parecía feo. He intentado muchas cosas pero no he podido solucionarlo. -_- Terminé usando la solución de Sorceror también. –

0

solución de Sorceror fue muy útil. Me he adaptado a un IStyledLabelProvider personalizada se utilice dentro de un 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; 
    } 
    } 

} 

Tenga en cuenta que estoy usando IMarker como datos para los elementos, y una TreeViewer (por lo que estoy recibiendo TreeItems), pero sus datos puede diferir, y su espectador puede ser un TableViewer; solo tienes que hacer tus propios ajustes.

Cuestiones relacionadas