Minimizing repaints in Swing and instanceof

Y

yakovfain

Hello,

There are several buttons on a Swing window, and the titiles of these
buttons are changing about a dozen times a second (sort of a dashboard
application). I need to speed up this processing as much as possible.
The current code is calling repaint() for each display of the new
button title. I'm thinking of using the Swing Timer class setting the
button's title directly. Is this more efficient?

Also, multiple repaints go to the event queue in a non-guaranteed
sequence.

One more question, the current code is performing if (src instanceof
JButton) then cast to JButton. In general, instanceof is an expensive
operation. Do you think that casting without the type check, but with
catching a ClassCastException would be faster?

Thanks,
Yakov
 
E

Eric Sosman

Hello,

There are several buttons on a Swing window, and the titiles of these
buttons are changing about a dozen times a second (sort of a dashboard
application). I need to speed up this processing as much as possible.

Buttons that change their labels at a rate of 12Hz
seem rather odd. By the time you can read it and decide
to click, it will have changed and you'll no longer know
what it's going to do when you click it. Are you sure
you don't want something like a JLabel?
The current code is calling repaint() for each display of the new
button title. I'm thinking of using the Swing Timer class setting the
button's title directly. Is this more efficient?

I'm not sure what you're proposing when you say you
want to "set the title directly." Do you mean somehow
avoiding the setText() method by mucking with the innards
of the JButton? That way lies madness, I think.

Perhaps you're thinking of just holding onto the latest
titles in a String[] or something, letting them change but
without changing what's on the screen. Then when the timer
fires, you pull everything out of the String[] and set all
the button legends at once. That can certainly be more
efficient (you go from updating the screen at 12Hz to
updating it at 1/T Hz), but it also means that the screen
doesn't accurately reflect the button state. If I click
on a button that says "Yes" when its actual state is "No,"
I may not like the results your GUI gives me.
Also, multiple repaints go to the event queue in a non-guaranteed
sequence.

I'm not sure why you think that's a problem.
One more question, the current code is performing if (src instanceof
JButton) then cast to JButton. In general, instanceof is an expensive
operation.

Expensive compared to what? What do your measurements
suggest?
Do you think that casting without the type check, but with
catching a ClassCastException would be faster?

If you "know" the source is a JButton, just go ahead and
cast it -- and *don't* catch the ClassCastException, because
if you get one it means your "knowledge" about the program is
wrong and you're ill-equipped to reason about how to recover.

If the source is "usually" a JButton, use instanceof.
It may sound like a duplication of the effort the cast itself
will go through, but by the time the JIT gets done with it
most of that extra effort will probably disappear. Once
again, measure.
 
Y

yakovfain

Buttons that change their labels at a rate of 12Hz
seem rather odd. By the time you can read it and decide
to click, it will have changed and you'll no longer know
what it's going to do when you click it. Are you sure
you don't want something like a JLabel?

Eric,

You're absolutely right, but I'm dealing with existing application that
receives a fast stream of numbers (prices) displayed on a dozen or so
JButtons, and the user can click on the price to make a purchase at
this price. Yes, people work at this speed :)
And because of this speed, users believe that the pressed the button
when the price A was displayed, but when they clicked on the button the
pice could have changed to B. Modal confirmation dialogs is not an
option (users do not want to delay their purchases because they do not
want to lose the best price).

When the new prices arrive into the event dispatch queue, each of them
calls repaint(), but since repaint does not happen immediately, the
sequence of received/displayed prices is not always guaranteed.
Expensive compared to what? What do your measurements suggest?

As per Java documentation, instanceof is considered to be expensive in
terms of time, so it's recommended to avoid it unless it's really
necessary. That's why I'm thinking, that if most of the components on
the screen are JButtons, the code will be more responsive if I'll just
assign the event source to a JButton type object within a try-catch
block.

If this crazy speed would not be required, everyting would have been
easier.
 
K

Knute Johnson

Hello,

There are several buttons on a Swing window, and the titiles of these
buttons are changing about a dozen times a second (sort of a dashboard
application). I need to speed up this processing as much as possible.
The current code is calling repaint() for each display of the new
button title. I'm thinking of using the Swing Timer class setting the
button's title directly. Is this more efficient?

Also, multiple repaints go to the event queue in a non-guaranteed
sequence.

One more question, the current code is performing if (src instanceof
JButton) then cast to JButton. In general, instanceof is an expensive
operation. Do you think that casting without the type check, but with
catching a ClassCastException would be faster?

Thanks,
Yakov

Why do you have to know that it is a JButton. Use a listener that only
listens to the buttons and you won't have to check that. You can have
multiple listeners.
 
T

Thomas Hawtin

There are several buttons on a Swing window, and the titiles of these
buttons are changing about a dozen times a second (sort of a dashboard
application). I need to speed up this processing as much as possible.
The current code is calling repaint() for each display of the new
button title. I'm thinking of using the Swing Timer class setting the
button's title directly. Is this more efficient?

Setting the buttons text will repaint the button anyway. Unless you have
a really bad graphics card, I suspect painting isn't the bottleneck.
have you used a profiler? Perhaps validation is taking up significant time.

Possibly you might want to throttle the updates if the painting can't
keep up to date.
Also, multiple repaints go to the event queue in a non-guaranteed
sequence.

Typically they will be merged.
One more question, the current code is performing if (src instanceof
JButton) then cast to JButton. In general, instanceof is an expensive
operation. Do you think that casting without the type check, but with
catching a ClassCastException would be faster?

We are talking a handful cycles. Comparing against a class should be
easier than against an interface. The comparison needs to be done for
the cast anyway. Nothing to see here.

Tom Hawtin
 
E

Eric Sosman

Eric,

You're absolutely right, but I'm dealing with existing application that
receives a fast stream of numbers (prices) displayed on a dozen or so
JButtons, and the user can click on the price to make a purchase at
this price. Yes, people work at this speed :)
And because of this speed, users believe that the pressed the button
when the price A was displayed, but when they clicked on the button the
pice could have changed to B. Modal confirmation dialogs is not an
option (users do not want to delay their purchases because they do not
want to lose the best price).

When the new prices arrive into the event dispatch queue, each of them
calls repaint(), but since repaint does not happen immediately, the
sequence of received/displayed prices is not always guaranteed.

Gives one a lot of confidence in the smooth operation
of the financial markets, doesn't it?
As per Java documentation, instanceof is considered to be expensive in
terms of time, so it's recommended to avoid it unless it's really
necessary. That's why I'm thinking, that if most of the components on
the screen are JButtons, the code will be more responsive if I'll just
assign the event source to a JButton type object within a try-catch
block.

That still seems like a bad idea. Why are only "most"
of the event sources JButtons, instead of "all?" Or rather,
if you've got multiple kinds of event sources, why send them
all to the same event listener? Couldn't you use one listener
for the JButtons (and only the JButtons) and a different
listener (with different code) for the JTextFields and other
doodads?
 
Y

yakovfain

That still seems like a bad idea. Why are only "most" of the event sources JButtons, >instead of "all?"

Existing code is processing mousePressed, so technically a user can
click between the buttons. But you're right, a custom event listener
can be used with buttons only.

BTW, in the original post I was writing about direct setting of button
titles.Since these settings would have been made from the Swing Timer
(which sends all through the event dispatch queue anyway), there would
not be any damage there. But if this direct setting would internally
call repaint(), there won't be any gain here either...
 
V

Vova Reznik

Existing code is processing mousePressed, so technically a user can
click between the buttons. But you're right, a custom event listener
can be used with buttons only.

BTW, in the original post I was writing about direct setting of button
titles.Since these settings would have been made from the Swing Timer
(which sends all through the event dispatch queue anyway), there would
not be any damage there. But if this direct setting would internally
call repaint(), there won't be any gain here either...

I think you should not use MouseListener here.
Right place to "pin" price is to work with
public void setPressed(boolean b) of ButtonModel.


Once button pressed - price pinned without waiting for firing ActionEvent.

Or, another place to research may be
javax.swing.plaf.basic.BasicButtonListener
that is responsible for any mouse activity.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top