A volte può accadere che i controlli forniti in SWT non siano appropriati alle esigenze dell'applicazione. In tal caso, è possibile estendere SWT implementando un proprio widget personalizzato. SWT è infatti dotato di un pacchetto org.eclipse.swt.custom, in cui sono contenuti i controlli personalizzati che non fanno parte del set principale di controlli di SWT, ma che sono necessari per implementare il workbench della piattaforma.
Controllo |
Scopo |
Stili |
---|---|---|
Controllo statico che visualizza l'animazione durante l'esecuzione di una lunga operazione. |
BORDER, HORIZONTAL, VERTICAL |
|
Simile al controllo Combo, ma è personalizzato per consentire l'utilizzo del controllo senza bordi. Questa classe è stata sviluppata per utilizzare controlli Combo all'interno di celle di tabella. |
BORDER, FLAT, READ_ONLY |
|
Simile al controllo Label, tuttavia, supporta la sostituzione di testo con puntini di sospensione. Supporta, inoltre, un effetto a gradiente per il colore di sfondo nella visualizzazione del workbench attiva. Non supporta la disposizione del testo. |
CENTER, LEFT, RIGHT, SHADOW_IN, SHADOW_OUT, SHADOW_NONE |
|
Simile al controllo TabFolder, tuttavia, supporta un'ulteriore configurazione dell'aspetto visivo di schede (superiore o inferiore) e bordi. |
BORDER, BOTTOM, TOP |
|
Controllo composito che dispone gli elementi secondari in righe o colonne e li separa mediante un controllo Sash per permettere all'utente di ridimensionarli. |
BORDER,HORIZONTAL, VERTICAL |
|
Controllo composito per riempire lo spazio disponibile mediante scorrimento e, opzionalmente, allungamento del suo contenuto. |
BORDER, H_SCROLL, V_SCROLL |
|
Controllo modificabile mediante il quale è possibile digitare un testo. Gli intervalli di testo all'interno del controllo possono avere tipi di carattere e colori differenti (primo piano e sfondo). |
BORDER, FULL_SELECTION, MULTI, SINGLE, READ_ONLY |
|
Controllo selezionabile che visualizza un elenco gerarchico di voci selezionabili dall'utente. L'elenco viene presentato in righe che visualizzano più colonne in cui sono rappresentati aspetti differenti delle voci. |
BORDER, SINGLE, MULTI, CHECK, FULL_SELECTION |
|
Controllo composito che dispone tre elementi secondari in orizzontale e consente il controllo programmatico dei parametri relativi a layout e bordi. Utilizzato nel workbench per implementare un'etichetta/barra degli strumenti/barra locale dei menu di visualizzazione. |
BORDER,FLAT |
Prima di implementare un widget personalizzato, è necessario tenere presente molti aspetti importanti:
Una volta stabilito che è necessario utilizzare un widget personalizzato e si è deciso quali piattaforme deve supportare, è possibile considerare diverse tecniche di implementazione dello stesso. Tali tecniche possono essere mescolate e armonizzate a seconda delle disponibilità nella sottostante piattaforma del sistema operativo.
Quando l'applicazione richiede un widget nativo che non è fornito da SWT, è necessario implementare un widget in modo nativo. Si può utilizzare un widget della piattaforma, un widget di terzi o qualsiasi altro widget di libreria condivisa in piattaforma.
Ciascuna piattaforma SWT è fornita sia di una libreria condivisa (ad esempio, una DLL su Windows) sia di un JAR (per i file di classe Java). La libreria condivisa contiene la funzionalità nativa completa richiesta per SWT, ma non costituisce un insieme completo delle funzioni disponibili sulla piattaforma. Per esporre la funzione nativa o i widget nativi non esposti da SWT, è necessario scrivere la propria libreria condivisa. In caso di utilizzo di un codice nativo su una piattaforma in combinazione con un codice trasferibile su un'altra piattaforma, assicurarsi di richiamare la libreria condivisa sulla piattaforma che contiene il widget nativo e il JAR su quella con il widget trasferibile.
Per implementare un widget nativo, è necessario conoscere JNI (Java Native Interface), l'API del widget nella libreria condivisa e le API della sottostante piattaforma del sistema operativo in C.
Il processo base di implementazione consiste nel determinare quale parte dell'API del widget nativo esporre nell'API Java e nello scrivere il codice Java che richiama i nativi per implementare il comportamento. Per richiamare la libreria condivisa, è necessario scrivere il codice JNI in C.
Una buona idea è quella di seguire i criteri di progettazione utilizzati per implementare SWT durante la creazione dell'implementazione del proprio widget nativo. Ad esempio, i nativi JNI devono essere singolarmente abbinati alle chiamate API effettuate nella libreria condivisa.
Un esempio completo di implementazione di un widget nativo personalizzato è reperibile in Creazione di widget personali mediante SWT.
Se il nuovo widget è simile nelle caratteristiche o nell'implementazione a un widget esistente, si potrebbe effettuare il wrap di un widget SWT esistente. Questa tecnica viene utilizzata per l'implementazione di TableTree.
Per effettuare il wrap di un widget, è necessario creare una sottoclasse del widget Composite o Canvas (a seconda che il controllo abbia o meno elementi secondari). Creare il widget incluso in un wrap nel costruttore per il widget personalizzato. Il widget risultante sarà trasferibile al 100% in Java perché per l'implementazione viene richiamata l'API del widget incluso in un wrap.
L'inclusione di un widget spesso consente di implementare widget personalizzati in maniera più semplice che partendo da zero. Tuttavia, occorre progettare attentamente l'API del nuovo widget. Suggerimenti importanti:
Considerare se il proprio widget è un "tipo di" widget incluso in un wrap o se ne utilizza giusto uno per l'implementazione. Ad esempio, una struttura di tabella non è un tipo di tabella. Non fa riferimento alle voci mediante un indice di numero di riga. Il controllo TableTree utilizza semplicemente una tabella per implementare la presentazione e aggiunge il comportamento di struttura. Se si sta effettuando il wrap di un widget a solo scopo di implementazione, l'API potrebbe apparire differente da quella del widget sottostante.
Inoltrare il minor numero di metodi ed eventi possibile. Non implementare nuovamente l'intera API del widget incluso, se non si vuole essere costretti a effettuare aggiornamenti a causa delle modifiche subite dall'API inclusa in una futura versione. È necessario inoltrare i metodi comuni alla maggioranza dei widget, come setFont, setForeground e setBackground.
Se vengono implementate la maggior parte delle API del widget incluso nel wrap, si prenda in considerazione la possibilità di esporre tale widget al livello API in modo da farlo utilizzare direttamente dal codice applicativo. In questo caso, si potrebbe anche riconsiderare la scelta di fornire un nuovo widget. Potrebbe risultare conveniente implementare la funzione come un "adattatore" che aggiunge funzionalità a un widget senza tuttavia fingere di esserlo (i visualizzatori JFace seguono questo modello).
Nota: la discussione è incentrata soltanto sull'estensione del comportamento di un widget mediante il processo di wrap. Si sconsiglia fortemente di estendere un widget mediante una sua collocazione in sottoclassi, perché lo si renderebbe dipendente dall'implementazione della superclasse.
A volte non esiste alcun codice nativo o widget che possa essere di supporto nell'implementazione del nuovo widget. In questo caso, è necessario progettare un widget personalizzato mediante le chiamate grafiche di SWT. Sebbene questa tecnica sia diventata abbastanza complicata, ha il pregio di produrre un'implementazione completamente trasferibile.
I controlli personalizzati sono implementati posizionando la classe Canvas o Composite in sottoclassi mediante le seguenti regole:
In un controllo personalizzato, lo stato interno viene mantenuto in variabili di istanza Java. API e stili vengono definiti in base alle esigenze del widget
L'implementazione interna di un widget personalizzato generalmente implica le seguenti attività principali:
Molti dei widget implementati in org.eclipse.swt.custom si avvalgono di questo approccio. Un esempio semplice può essere trovato in CLabel.
Ulteriori informazioni sui widget personalizzati sono reperibili in Creazione di widget personali mediante SWT.