Win a copy of Murach's Python Programming this week in the Jython/Python forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

continue changing background color of JButton  RSS feed

 
Pete Lin
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi:
I tried to change JButton background color every 2 second, but it most of the time only shows the last color, can anyone point out what I did wrong?
 
Peter Muster
Ranch Hand
Posts: 74
5
Eclipse IDE Python Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This article might help you achieving this.

The solution will probably be similar to this:

I haven't tried it out though but I hope you get the idea what you have to do. With a bit of trial and error and reading the Oracle documentation you should be able to achieve what you want easily. :-)
 
Campbell Ritchie
Sheriff
Posts: 53720
127
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Christian Pflugradt wrote:. . .. . .
If you have the good fortune to use Java8, you can reduce that to a λ
 
Fred Kleinschmidt
Bartender
Posts: 507
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Just using the invokeLater() will not completely solve the problem. You need to remove the loops from actionPerformed() and put them in the run() method instead.
Otherwise the loops block the Event Thread, preventing the repaint from doing anything.
 
Rob Camick
Ranch Hand
Posts: 2752
11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Never use an empty while loop to waste time.

Using invokeLater() won't help. The code is already executing on the Event Dispatch Thread (EDT) so the GUI can't repaint itself until all the code in the actionPerformed() method is finished executing.

You need your code to execute on a separate Thread so the EDT can continue to respond to events and the GUI can continue repainting itself.

You could create a separate Thread and then in that thread you would need to use the invokeLater() to add the code that updates the GUI back onto the EDT.

Or you can use a SwingWorker and publish results so the GUI can update itself.

Read the section from the Swing tutorial on Concurrency in Swing for more information on the above concepts and working examples of a Swing Worker.

The other option is to start a Swing Timer. Then when the Timer fires its event you update the background. The tutorial also has a section on How to Use Timers.

I suggest you keep a tutorial link handy for all the Swing basics.
 
Brian Cole
Author
Ranch Hand
Posts: 932
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It seems to me that calling repaint() shouldn't help. The implementation of setBackground() already calls repaint().

Pete Lin wrote:

Busy loops like this one are almost always a bad idea. This particular busy loop is inside an event handler, which is doubly bad. This sort of thing will generally make your GUI unresponsive. You might want to look at the javax.swing.Timer class.

As for why you're not seeing the background color change, it's hard to say without more information. Could you provide a short example we could actually compile and run? (Even if you did that, you should tell us which LookAndFeel you are running with.)
 
Les Morgan
Rancher
Posts: 752
17
C++ Java MySQL Database Netbeans IDE Oracle Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Pete Lin wrote:Hi:
I tried to change JButton background color every 2 second, but it most of the time only shows the last color, can anyone point out what I did wrong?


Pete,
As pointed out by Brian, your delay loop is very unfortunate--it keeps the thread busy and does not allow any other processing to go on, so when you do change color, the effect is not able to propagate into your button. A timer would work a lot better for you.
 
Pete Lin
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi:
This is a really excellent forum, I received so many excellent suggestions. After modification, it is working very nicely now. I don't claim I know very deep about the thread. I am extending a Thread class, and instantiate it in my actionPerformed method, below is my implementation. Thanks everyone.
 
Rob Camick
Ranch Hand
Posts: 2752
11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
All Swing components need to be updated on the EDT.

Therefore when you change the background of the component you need to wrap that code in a SwingUtilities.invokeLater().

Read my previous answer and read the tutorial on Concurrency.
 
Brian Cole
Author
Ranch Hand
Posts: 932
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok, first, that's a big improvement over the original code.

Second, this is probably violating Swing's single-threading rule. (Either that or it's calling sleep() from the EDT, which would be worse.)

That's one reason to use a javax.swing.Timer. It fires events on the EDT.

But if you want to keep your code mostly intact, wrap the call to setBackground() inside of an invokeLater(). Posts above show how to do this, except they are wrapping repaint() instead of setBackground().
 
Paul Clapham
Sheriff
Posts: 22185
38
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Pete Lin wrote:I am extending a Thread class, and instantiate it in my actionPerformed method, below is my implementation.


You don't need to do that, and in fact you shouldn't do it. The high-level description of the Swing Timer class is this: "Every X seconds do action Y". So all you need to do yourself is to specify X and Y. All of the waiting and timing is taken care of by the Timer class. If you find yourself calling Thread.sleep() then you're doing it wrong. Note also that you can tell the Timer to only do the action once, which is quite frequently what you want.

And you're not limited to using only one Timer. It looks to me like you want to wait a bit, then change the background based on the selected index, then wait another bit and change the background back to white. So you'd use one Timer to do the first half and a second Timer to do the second half.
 
Pete Lin
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What you mentioned is exactly what I want to do. I am changing the code to be. I have not used Timer before, I need to look it up.
 
Paul Clapham
Sheriff
Posts: 22185
38
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That's good. So when you finish looking up Timer (don't forget to read a Timer tutorial) and get that code rewritten, you could post the new version here for comments.
 
Campbell Ritchie
Sheriff
Posts: 53720
127
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul Clapham wrote:. . . Timer tutorial . . .
Try this one.
 
Les Morgan
Rancher
Posts: 752
17
C++ Java MySQL Database Netbeans IDE Oracle Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Pete look at my previous post with code, it shows how to use the Timer class to do what you have described.
Pete Lin wrote:What you mentioned is exactly what I want to do. I am changing the code to be. I have not used Timer before, I need to look it up
 
Pete Lin
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I know how to use one timer, but how do I use 2 timers together?

Thanks
 
Les Morgan
Rancher
Posts: 752
17
C++ Java MySQL Database Netbeans IDE Oracle Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Pete Lin wrote:I know how to use one timer, but how do I use 2 timers together?

Thanks

There you go two Swing timers together--use Swing because multiple timers all run off of the same thread--not as resource intensive.
 
Paul Clapham
Sheriff
Posts: 22185
38
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Pete Lin wrote:I know how to use one timer, but how do I use 2 timers together?


What does "together" mean? It's not much different than the way you used two JButtons "together" in code you posted earlier. You decide what the timers should do, and at what point they should be started, and then you write the code (what they should do) and put it in the right place (when they should be started).

So, why don't you look at your design and write down in your native language what you want each timer to do? And then write down what situation should cause the timer to be scheduled?
 
Pete Lin
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here is my updated code, I set initial delay of time2 to 500 to enable the background back to white for 500.
Timer timer1 = new Timer(1000, new Timer1ActionListner());
Timer timer2 = new Timer(1000, new Timer2ActionListner());
 
Paul Clapham
Sheriff
Posts: 22185
38
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey, that looks like a pretty good attempt! Key question, is it doing what you wanted it to do?
 
Pete Lin
Greenhorn
Posts: 6
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, and it works pretty smooth. Of course, there is always improvement to be done. :-)
Thanks
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!