Devon has the best answer for the how. As for the why, the basic problem is that the setIcon function doesn't contain the code that repaints your component. The flow looks like this:
1) You click something on the GUI
2) An event is generated, Swing calls all the listeners
3) Your code is triggered and run, setIcon is called
4) Your code finishes running and control returns to Swing
5) Swing paints any new/changed components, etc.
All of this happens on one thread. You want your delay to occur after step 3, but you don't want to block the current thread because then step 5 won't execute until after the delay. Devon's solution uses a SwingWorker to put the delay on a different thread so it won't block step 5.