1

I have a fractal generation component (a subclass of JPanel) inside a JFrame. When the user resizes the window, it takes quite a while to update the fractal to the new size.

I currently have a ComponentListener on the JPanel, but its componentResized event is called every time the user moves the mouse while dragging the window border. This means that the fractal is told to resize many times, and slowly (over the course of a few minutes) grows to the new size.

Is there a way to be notified when the user releases the mouse button, so that I can only change the fractal size when the user has finished resizing?

Others have reported this happening when the listener is attached to the JFrame instead, but this doesn't work for me (and others), for some reason.

Community
  • 1
  • 1
Harry Cutts
  • 1,352
  • 11
  • 25
  • Can you explain why frame render slowly, it might be something should look into. – Pau Kiat Wee Apr 19 '12 at 13:46
  • Normally the frame renders quite quickly, however I am in the process of allowing the user to enter their own fractal formulas in the form of Lua scripts. I'm using LuaJ to run the scripts, which is slowing the rendering down. – Harry Cutts Apr 19 '12 at 13:49
  • Does anything substantive happen with the fractal on window resize? If it is just 'stretched', you might try painting it to a `BufferedImage` and painting the image instead. – Andrew Thompson Apr 19 '12 at 13:59
  • Yes, the fractal is generated again with more or less detail depending on whether the window has been enlarged or shrunk, so it's not just a stretch. – Harry Cutts Apr 19 '12 at 14:05

3 Answers3

4

Instead of starting the calculation each time you receive a receive-event, you can only start the calculation after you received the last event by using a timer, e.g. in pseudo-code (or at least code which I typed here directly and not in my IDE)

private Timer recalculateTimer = new Timer( 20, myRecalculateActionListener );

constructor(){
  recalculateTimer.setRepeats( false );
}
@Override
public void componentResized(ComponentEvent e){
  if ( recalculateTimer.isRunning() ){
    recalculateTimer.restart();
  } else {
    recalculateTimer.start();
  }
}

And you can still combine this with Andrews suggestion to use an image which you stretch until the calculation has actually finished.

Robin
  • 36,233
  • 5
  • 47
  • 99
  • 1
    many people, many views, I use Boolean with Timer#restart inside all Listeners, +1 EDIT and important on 350 -600 miliseconds, because all good mediaplayer have got cca half second delay, I think that this dealy is pretty acceptable – mKorbel Apr 19 '12 at 14:25
1
  • you have look at HierarchyListener, where you can listening for HierarchyEvent with interface to HierarchyBoundsListener

  • basically nothing wrong with ComponentListener, but you have to wrapping expected events to the Swing Timer, in the case that events repeated, only to call Timer#restart(), output from Swing Timer should be Swing Action

mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • Unfortunately, `HierarchyBoundsListener` behaves in the same way as `ComponentListener`. However, I will try using a timer. Thanks. – Harry Cutts Apr 19 '12 at 14:18
  • Hmm, I just suggested the timer before it was included in your comment. Makes my answer look very redundant. +1 for the suggestion – Robin Apr 19 '12 at 14:22
0

It's a bit late, but it looks like no one found the correct answer. I found that when you call child.updateUI() inside a ComponentListener (componentResized block) of a window, this child resizes it self and updates its content. Using timers is unsafe.

napsta32
  • 31
  • 1