Re: Could this be done better
In article <87zjbg97c5.fsf@Equus.decebal.nl>, Cecil Westerhof
(Cecil@decebal.nl) says...
I was just wondering if this could be done better. Especially
?updateColour?. First I did not removed the text, but then I could see
the colour changing before the text was changed. This way I find more
pleasing and I do not notice that the text disappears.
import java.awt.*;
import java.util.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class ColourCycling extends JFrame {
First lesseon: Never derive from JFrame, always derive views from JPanel
and put that into a frame.
Reason: You may want use this component elsewhere (inside another panel
probably).
// public functions
public ColourCycling() {
java.util.Timer colourTimer = new java.util.Timer();
getContentPane().setBackground(background);
setLayout(new GridBagLayout());
label.setFont(new Font("serif", Font.BOLD, 25));
add(label);
pack();
Lesson two: pack() is useless, if you set the rame size manually, after
packing:
setSize(getWidth(), 3 * getHeight());
Lesson three: Never set the size of the frame directly. pack(9 should be
enough.
The frame size is the size of the frame including its decorations.
Different systems have thicker frames, smaller or larger fonts in the
frame title. If you set the size directly, you might cut off the bottom
or right part of the content,if the frame decorations are larger than
expected, or you leave space, if it is smaller.
You want the frame to wrap around a panel, let the layout manager figure
out the site of the content. If realy necessary, set the preferredSize
of a component. Use pack() after you have built your component hierarchy
and leave the frame size alone.
label.setBackground(background);
updateColour(getCurrentColour());
colourTimer.schedule(new SwitchColour(), delay, delay);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle(description);
setVisible(true);
}
public static void main(String[] args) {
new ColourCycling();
}
Lesson four. Never create or manipulatre Components outside of the Event
Dispatching Thread.
You want:
EvenQueue.invokeLater(new Runnable(){
public void run(){
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentpane().add(new ColourCycling());//assume CC ext JPanel
frame.pack();
frame.setVisible(true);
}
});
// private classes
private class Colour {
Lesson five: Naming a private class the same as an API class works, but
is not well readable. Find a better name, for example
"ColorWithDescription" or "NamedColor" or "ChoosableColor" or whatever
is appropriate for its use.
// public
public Colour(Color color, String description) {
this.color = color;
this.description = description;
}
//...
private class SwitchColour extends TimerTask {
public void run() {
updateColour(getNextColour());
}
}
Back to lesson four: Never create or manipulate Components outside of
the Event Dispatching Thread. "invokeLater" is your friend:
Since the TimerTask is executed by a java.util.Timer, it is executed on
e thread other than the Swing Event Dispatching Thread, where everything
has to be rendered. You want to push the operation to the event
dispatching thread:
EventQueue.invokeLater(new Runnable(){
public void run(){
updateColour(getNextColour());
}
});
By the way: It doesn't matter, if you use "EventQueue.invokeLater" or
"SwingUtilities.invokeLater".
Kind regards,
Wanja
--
...Alesi's problem was that the back of the car was jumping up and down
dangerously - and I can assure you from having been teammate to
Jean Alesi and knowing what kind of cars that he can pull up with,
when Jean Alesi says that a car is dangerous - it is. [Jonathan Palmer]