2012-01-23 21 views
5

Sviluppo un'applicazione Eclipse RCP e ho riscontrato un problema con uno Table. Abbiamo alcuni dati nel database in formato booleano e gli utenti vogliono vedere quel campo usando checkbox.Come allineare l'immagine al centro della cella della tabella (Tabella SWT)

ho cercato di attuare utilizzando Button(SWT.CHECK) come Table Editor, ma ha funzionato troppo lento :(

Ho cercato di usare 2 immagini - controllati e incontrollati check-box, funziona, ma posso' t allinearli al centro, essi sono allineati a sinistra automaticamente

ho anche trovato come catturare SWT.MeasureItem e SWT.PaintItem eventi e li elaborare manualmente dal cambiamento event.x campo, ma ho avuto un problema -. non riesco a misura quale colonna o pittura al momento, perché Event non mi fornisce quell'informazione

È l'unico modo per allineare le immagini al centro modificando i dati degli eventi durante il ridisegno, oppure potrebbero esserci altri modi per rappresentare i dati booleani tramite check-box? Non ho bisogno di modificarli ora, quindi la modalità di sola lettura dovrebbe essere sufficiente.

+0

Sono quasi scioccato dal fatto che lasciare che le finestre di selezione del SO siano più lente delle immagini. –

+0

@EdwardThomson Penso che dipenda davvero dall'implementazione .. – Sorceror

risposta

8

Puoi aggiungere PaintListener al vostro tavolo e quando dipingerà colonna selezionata (colonna 5 nel mio caso), controllare le dimensioni di riga e allineare l'immagine da soli ..

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

Ecco l'esempio utilizzando OwnerDrawLabelProvider: http://bingjava.appspot.com/snippet.jsp?id=3221

ho combinato con il legame di Tonny per TableViewers and Nativelooking Checkboxes e creato a portata di mano classe CenteredCheckboxLabelProvider astratta

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

Gloriosa, grazie mille! Ho appena dovuto fare una piccola modifica: sto usando un TreeViewer, quindi gli elementi negli eventi sono TreeItem invece di TableItem; Ho appena usato instanceof per farlo funzionare con entrambi i casi. –

+0

Ahi, ho parlato troppo presto ... Ha avuto problemi con il colore di sfondo dello stato selezionato, era diverso da tutte le altre celle della stessa riga e sembrava brutto. Ho provato molte cose ma non ero stato in grado di risolverlo. -_- Ho finito per usare anche la soluzione di Sorceror. –

0

soluzione Sorceror è venuto in aiuto. Ho adattato ad un IStyledLabelProvider personalizzato da utilizzare all'interno di 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; 
    } 
    } 

} 

Si noti che sto usando iMarker come dati per gli elementi, ed un TreeViewer (così sto ricevendo TreeItems), ma i dati potrebbe essere diverso e il tuo viewer potrebbe essere un TableViewer; devi solo apportare le tue modifiche.

Problemi correlati