Bonjour,
Pour un petit programme, j'ai écrit une classe permettant facilement d'indiquer qu'un composant est indisponible le temps qu'une tâche de fonds s'éxecute.

Cette classe utilise en interne une JXBusyLabel de SwingX (requis pour fonctionner).

L'objectif premier est de pouvoir rendre "occupé" n'importe quel composant sans trop d'effort. Mon besoin était de pouvoir le faire sur une JTable (le temps qu'elle charge les données à afficher).

Créer un gestionnaire:

Code :
1
2
3
4
5
 
/** Create an handler for managing the "busy" state
 *  This handler can be used on the controller or model layer
 */
BusyHandler handler = BusyFactory.create( monComposant );
Indiquer que le composant est occupé:

Code :
1
2
3
4
 
/** Go on a busy state
 */
handler.busy();
Indiquer que le composant n'est plus occupé:

Code :
1
2
3
4
 
/** Return to a normal state
 */
handler.done();
ce qui donne sur une JTable (avec une animation)



Voici le code:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package org.divxdede.filemanager.ui.busy;
 
import java.awt.Color;
import java.awt.Component;
import java.awt.Point;
import java.awt.Window;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import org.jdesktop.swingx.JXBusyLabel;
import org.jdesktop.swingx.JXPanel;
 
/**
 * Utilitaire pour rendre "occupé" un composant swing.
 * <p>
 * Les méthodes <strong>create</strong> modifie le rendu d'un composant afin 
 * d'indiquer à l'utilisateur que ce dernier est occupé.
 * <p>
 * Un <code>BusyHandler</code> est retourné afin de permettre à l'appelant 
 * d'indiquer que la tâche occupant le composant est terminée.
 * 
 * @author André Sébastien
 */
public abstract class BusyFactory {
 
    /** Busy a specified component
     *  @param comp Component to create
     *  @return BusyHandler Handler for complete the task and stop the create state
     */
    public static BusyHandler create( JComponent comp )  {
        return create( comp , Color.GRAY );
    }
 
    /** Busy a specified component
     *  @param comp Component to create
     *  @param shadowColor Shadowing color used over the component while it is create
     *  @return BusyHandler Handler for complete the task and stop the create state
     */
    public static BusyHandler create( JComponent comp  , Color shadowColor ) {
        return new BusyHandlerImpl(comp, shadowColor );
    }
 
    /** Create a component used as a glasspane
     */
    private static JComponent createGlassPane() {
        JXPanel panel = new JXPanel();
        panel.setLayout(null);
        panel.setOpaque(false);
        panel.setName("busy-glasspane");
        return panel;
    }
 
    /** Duplicate a layout component (location & size) on another component.
     */
    private static void layout( JComponent source , JComponent dest ) {
 
        Point point     = source.getLocation();
        Point rootPoint = SwingUtilities.convertPoint( source.getParent(), point , dest.getParent() );
 
        dest.setLocation(rootPoint);
        dest.setSize( source.getSize() );
    }
 
    /** BusyHandler implementation
     */
    static class BusyHandlerImpl implements BusyHandler {
 
        private JComponent  comp        = null;
        private Color       shadowColor = null;
 
        private JComponent  glassPane   = null;
        private Component[] comps       = null;
 
        public BusyHandlerImpl( JComponent comp , Color shadowColor ) {
            this.comp        = comp;
            this.shadowColor = shadowColor;
        }
 
        public synchronized void busy() {
            if( this.glassPane != null ) return;
 
            synchronized( comp.getTreeLock() ) 
            {
                Window w = SwingUtilities.getWindowAncestor(comp);
                if( w instanceof JFrame ) {
                    JFrame frame  = (JFrame)w;
 
                    /** Get a glasspane component
                     */
                    this.glassPane = (JComponent)frame.getGlassPane();
                    if( this.glassPane.getName() == null || !glassPane.getName().equals("busy-glasspane") ) {
                        this.glassPane = createGlassPane();
                        frame.setGlassPane( this.glassPane );
                    }
 
                    synchronized( this.glassPane.getTreeLock() ) 
                    {
                        /** Create a Busy Label 
                         */
                        JXBusyLabel label = new JXBusyLabel();
                        label.setHorizontalAlignment( label.CENTER );
 
                        /** Create a white-shadow
                         */
                        JLabel shadow = null;
                        if( shadowColor != null ) {
                            shadow = new JLabel();
                            shadow.setBackground( new Color(shadowColor.getRed(),shadowColor.getGreen(),shadowColor.getBlue(),100) );
                            shadow.setOpaque(true);
                        }
 
                        /** Add the Busy label to the glasspane
                         */
                        if( shadow != null ) this.glassPane.add( shadow );
                        this.glassPane.add( label );
                        if( shadow != null ) layout( comp , shadow );
                        layout( comp , label );
 
 
                        if( shadow != null ) {
                            this.comps = new Component[]{ shadow , label };
                        }
                        else
                            this.comps = new Component[]{ label };
 
                        /** Show the GlassPane if it's not the case
                         */
                        this.glassPane.setVisible(true);
 
                        /** Start animation
                         */
                        label.setBusy(true);
                    }
                }
                else {
                    throw new IllegalStateException("Component don't have a JFrame ancestor");
                }
            }
        }
 
        public synchronized void done() {
            if( comps == null || glassPane == null ) return;
 
            if( ! SwingUtilities.isEventDispatchThread() ) {
                SwingUtilities.invokeLater( new Runnable() {
 
                    public void run() {
                        done();
                    }
                } );
                return;
            }
 
            synchronized( glassPane.getTreeLock() ) {
                for(Component c : comps) {
                    if( c instanceof JXBusyLabel ) {
                        ((JXBusyLabel)c).setBusy(false);
                    }
                    glassPane.remove(c);
                }
            }
            glassPane = null;
            comps = null;
        }
    }
}
et

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package org.divxdede.filemanager.ui.busy;
 
/**
 * BusyHandler allow to notify that the busy task is completed and that
 * we can stop to render the component as a busy component.
 * 
 * @author André Sébastien
 */
public interface BusyHandler {
 
    /** Set the underlying task as busy.
     *  
     */
    public void busy(); 
 
    /** Done the underlying task.
     */
    public void done();
}
Cette classe n'est pas parfaite ( le rendu est peu configurable, etc...) mais ca peut être un point de départ pour implémenter une version plus "générale".

En esperant que ca peut re-servir.

Sébastien.