Eclipse (Swing) - Ajouter des composants dans un JTable

Afin d’améliorer l’ergonomie de certaines interfaces, il peut être utile d’ajouter des éléments interactifs (zones de texte, boutons radio…) directement dans les cellules d’un tableau.

Pour ce faire, l’API Swing permet de mettre rapidement en place des TableCellRenderer qui définissent le contenu des cellules. De base, une cellule est en fait un JLabel : on peut donc améliorer l’affichage en le remplaçant par une zone de texte srollable. C’est à partir de ce moment que les ennuis commencent…

Regardons tout d’abord le code nécessaire à la mise en place de cette zone de texte :

Définition du renderer personnalisé dans la dernière colonne du tableau :

Table table = new JTable() {
                    private static final long serialVersionUID = 3592907806336215067L;
                    public boolean isCellEditable(int rowIndex, int vColIndex) {
                        return (vColIndex==this.getColumnCount()-1);
                    }
                };
TableColumn col = table.getColumnModel().getColumn(resultColumnIndex);
TextAreaCellRenderer renderer = new TextAreaCellRenderer();
col.setCellRenderer(renderer);

Code du renderer :

import java.awt.Color;
import java.awt.Component;
 
import javax.swing.BorderFactory;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.table.DefaultTableCellRenderer;
 
public class TextAreaCellRenderer extends DefaultTableCellRenderer {
 
    private static final long serialVersionUID = -3987688353662913146L;
 
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value,
        boolean isSelected, boolean hasFocus, int row, int column) {
 
        // Customize it
        JTextArea textArea = new JTextArea(value.toString());
        textArea.setEditable(false);
        textArea.setWrapStyleWord(true);
        textArea.setLineWrap(true);
        JScrollPane pane = new JScrollPane(textArea);
        pane.setBorder(BorderFactory.createLineBorder(Color.BLACK, 0));
        pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        pane
            .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        return pane;
    }
}

Ces quelques lignes suffisent à faire apparaître une zone de texte dans les cellules en question. Cependant, impossible d’utiliser les barres de défilement!! En effet, comme expliqué dans ce forum, Swing n’ajoute pas réellement la zone de texte dans la cellule, mais plutôt une image de celle-ci.

Pour rendre les barres de défilement actives, voici le principe à mettre en place :

Au clic sur la cellule, il faut entrer en mode édition. Ainsi, une nouvelle zone de texte sera définie comme CellEditor et sera utilisable!

Voici donc le complément de code à mettre en place :

Définition de l’éditeur personnalisé :

Table table = new JTable() {
                    private static final long serialVersionUID = 3592907806336215067L;
                    public boolean isCellEditable(int rowIndex, int vColIndex) {
                        return (vColIndex==this.getColumnCount()-1);
                    }
                };
TableColumn col = table.getColumnModel().getColumn(resultColumnIndex);
TextAreaCellRenderer renderer = new TextAreaCellRenderer();
TextAreaCellEditor editor = new TextAreaCellEditor();
col.setCellEditor(editor);
col.setCellRenderer(renderer);

Code de l’éditor :

import java.awt.Color;
import java.awt.Component;
 
import javax.swing.AbstractCellEditor;
import javax.swing.BorderFactory;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.table.TableCellEditor;
 
public class TextAreaCellEditor extends AbstractCellEditor implements
    TableCellEditor {
 
    private static final long serialVersionUID = -9030406143699523582L;
 
    private String editingValue;
 
    @Override
    public Component getTableCellEditorComponent(JTable table, Object value,
        boolean isSelected, int row, int column) {
 
        editingValue = value.toString();
 
        // Customize it
        JTextArea textArea = new JTextArea(valueStr);
        textArea.setEditable(false);
        textArea.setWrapStyleWord(true);
        textArea.setLineWrap(true);
        JScrollPane pane = new JScrollPane(textArea);
        pane.setBorder(BorderFactory.createLineBorder(Color.BLACK, 0));
        pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        pane
            .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        return pane;
    }
 
    @Override
    public Object getCellEditorValue() {
        return editingValue;
    }
 
    @Override
    public void cancelCellEditing() {
        super.cancelCellEditing();
    }
}

Maintenant, le contenu de la cellule est défilant.


Fichier(s) joint(s) :



Eclipse (PDE) - Gérer les activités

Lors du développement d’applications Éclipse, on peut rapidement être confronté à la gestion des droits d’accès utilisateurs sur certaines fonctionnalités.

Heureusement, cela peut facilement être géré par les Activités : vous trouverez un très bon guide dans la documentation officielle, mais pour résumer, on peut dire qu’une activité est un groupe de fonctionnalités régies par des règles d’utilisation ou d’accès.

Pour créer ces règles, dans le fichier "plugin.xml", il faut utiliser le point d’extension

org.eclipse.ui.activities

C’est ensuite le "pattern" qui définira la règle à appliquer : sous forme d’expression régulière, son format est le suivant :

plug-in-identifier + "/" + local-identifier

Voici un exemple :

Dans le fichier "plugin.xml", on définit l’activité suivante : 

 Puis on lui affecte un pattern :

Ainsi, nous avons défini la règle suivante : le profil "developer" n’aura accès qu’aux fonctionnalités du plugin

com.client

dont le nom contient

ui.commands.developer

Pour faire appliquer cette règle à l’IDE, voici le code à implémenter :

public class ProfileManager {
    private static final String ACTIVITY_DEVELOPER_ID    = "com.client.ui.activities.profile.developer";
    public static void refreshGUIAccordingToProfile(){
        IWorkbenchActivitySupport activitySupport = PlatformUI.getWorkbench()
            .getActivitySupport();
        // List of activities to be activated
        Set enabledActivities = new HashSet();
 
        // Retrieve list of activities currently activated
        Set currentlyEnabledActivities = PlatformUI.getWorkbench()
            .getActivitySupport().getActivityManager().getEnabledActivityIds();
        // Remove activities which are related to user's profile
        // I.e. Keep activities activated by user via Windows > Preferences
        for (String anActivity : currentlyEnabledActivities) {
            if (!isAProfileRelatedActivity(anActivity)) {
                enabledActivities.add(anActivity);
            }
        }
        enabledActivities.add(ACTIVITY_DEVELOPER_ID);
        activitySupport.setEnabledActivityIds(enabledActivities);
   }
}

Ce code est à appeler au lancement du plugin dans l’IDE : il fait appel simplement à l’interface de gestion des activités par défaut et y ajoute celle que nous venons de créer!

Vous disposer maintenant de tout le nécessaire pour paramétrer l’interface de votre application selon différent profils utilisateurs.


Fichier(s) joint(s) :

Eclipse (SWT) : sélectionner une cellule dans une Table

Cela pourrait paraître enfantin et pourtant, on peut plutôt y perdre quelques cheveux!! Attention, je parle pas ici des JTable de swing qui sont facilement utilisables et extensibles, mais bien de l’objet simpliste Table de SWT.

Le principe basique des Tables est d’afficher une liste de données en ligne (les colonnes représentent les attributs). Le constructeur de l’objet permet facilement d’autoriser la sélection d’une ligne entière, mais rien ne permet d’activer à l’aide de la souris la sélection d’une cellule : il faut pour cela un peu d’imagination. Jetons d’abord un œil au code avant de le commenter :

TableViewer tableViewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
            | SWT.V_SCROLL | SWT.FULL_SELECTION);
tableViewer.getTable().addListener(SWT.MouseDown, new Listener() {
            TableItem item = null;
            int       oldi = -1;
            public void handleEvent(Event event) {
                Point pt = new Point(event.x, event.y);
                if (item != null && !item.isDisposed()) {
                    item.setBackground(oldi, Display.getCurrent()
                        .getSystemColor(SWT.COLOR_WHITE));
                    item.setForeground(oldi, Display.getCurrent()
                        .getSystemColor(SWT.COLOR_BLACK));
                }
                item = table.getItem(pt);
                if (item == null)
                    return;
                for (int i = 0; i < table.getColumnCount(); i++) {
                    Rectangle rect = item.getBounds(i);
                    if (rect.contains(pt)) {
                        table.deselectAll();
                        item.setBackground(i, Display.getCurrent()
                            .getSystemColor(SWT.COLOR_LIST_SELECTION));
                        item.setForeground(i, Display.getCurrent()
                            .getSystemColor(SWT.COLOR_WHITE));
                        oldi = i;
                        int index = table.indexOf(item);
                        System.out.println("Sélection de la ligne " + index + " - colonne " + i + " : valeur '"+ item.getText(i) +"'");
                    }
                }
            }
        });
    }

Le principe est donc le suivant :

Lorsque l’utilisateur clic dans le tableau, on récupère la position x et y du clic et on lui demande de nous retourner l’élément situé sous la souris (l’objet item). Pas terrible n’est-ce pas?!

Au niveau du code on a donc bien récupéré notre objet, mais au niveau visuel, c’est toute la ligne du tableau qui est sélectionnée! Pour y remédier, on dé-sélectionne immédiatement tout, puis on affecte à notre cellule une couleur d’arrière-plan correspondant à la couleur d’un élément sélectionné… On garde en mémoire notre cellule pour lui redonner des couleurs normales lorsqu’une autre sera clicquée.

Je vous l’accorde, c’est du bricolage, mais l’objet Table de SWT est vraiment très basique et c’est le seul moyen d’arriver à ce résultat ( à moins que je ne me trompe…)


Fichier(s) joint(s) :