views:

312

answers:

4

I am trying to flash the background colour in a textfield. My timer setup is as follows:

 Flash flash = new Flash();                      //set up timer
 tmr = new javax.swing.Timer(1000, new Flash());
 tmr.addActionListener(flash);
 tmr.setInitialDelay(0);
 tmr.setRepeats(true);
 tmr.start();                 

My actionListener is as follows:

 static class Flash implements ActionListener
 {
    public void actionPerformed(ActionEvent evt)
    {
        if (flasher)
        {
            SpreademPanel.historyPnl.NameTxt.setBackground(Color.white);
        }
        else
        {
            SpreademPanel.historyPnl.NameTxt.setBackground(Color.pink);
        }
        flasher = !flasher;
    } //actionPerformed
} //Flash

Now, when I put this in debug and follow the action, the program does repeatedly step through flash and toggle between the two alternatives. But onscreen, only the first toggle occurs. After that, no action, although flash is still functioning.

What is wrong here?

Thanks in advance for any help.

+2  A: 
tmr = new javax.swing.Timer(1000, flash);
tur1ng
+1  A: 

I tried your code and it works fine.

Why do you use a static context for SpreademPanel.historyPnl.NameTxt?

EDIT

You might want to redesign your class to pass the component in the constructor.

private class Flash implements ActionListener
{
    private boolean flasher = false;
    private JComponent component;

    public Flash(JComponent component) {
        this.component = component;
    }

    public void actionPerformed(ActionEvent evt)
    {
        if (flasher)
        {
            component.setBackground(Color.white);
        }
        else
        {
            component.setBackground(Color.pink);
        }
        flasher = !flasher;
    } //actionPerformed
} //Flash

and then init it with

 Flash flash = new Flash(SpreademPanel.historyPnl.NameTxt);
 Timer tmr = new javax.swing.Timer(1000, flash);
 tmr.start();
Peter Lang
+1 for ditching statics.
Tom Hawtin - tackline
+1  A: 

There are a couple of problems here.

The first obvious thing is that you appear to be using mutable statics. This is a really bad idea and indicates (and causes!) confusion. In this particular case, one of the problems caused is that the flasher static is shared.

Flash flash = new Flash();                      //set up timer
tmr = new javax.swing.Timer(1000, new Flash());
tmr.addActionListener(flash);

We are adding two Flash actions. Ordinarily this would be bad, but just produce an undetectable "bug". The colour would be set twice.

Bring these two things together, and we have two actions without a break that perform the same toggle. Two toggles. The state does not change (although there are repaint, property change events, etc.).

So, don't use mutable statics, and keep the code clean.

Tom Hawtin - tackline
You are completely correct about confusion, I am a novice at Java and have not formerly run across the concept of "static" in the languages I've used, but I am slowly getting my head around all its implications: this was a new one, and thanks for pointing out the intricacies of this case.I moved the timer stuff out of the main program, back into SpreademPanel, where it apparently belongs, and now it works fine.
John R Doner
A: 

This is so wrong:

import java.awt.*;
import java.awt.event.*;
import java.awt.event.ActionListener;
import java.util.LinkedList;
import java.util.Queue;
import javax.swing.*;

public class FlashTest extends JPanel {

    private static final Font font = new Font("Serif", Font.PLAIN, 32);
    private static final String s = "Godzilla alert!";

    FlashTest() {
        this.setPreferredSize(new Dimension(256, 96));
        this.setBackground(Color.red);
        Timer t = new Timer(50, new Flash(this));
        t.start();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setFont(font);
        int xx = this.getWidth();
        int yy = this.getHeight();
        int w2 = g.getFontMetrics().stringWidth(s) / 2;
        int h2 = g.getFontMetrics().getDescent();
        g.setColor(Color.black);
        g.drawString(s, xx / 2 - w2, yy / 2 + h2);
    }

    private static class Flash implements ActionListener {

        private final float N = 32;
        private final JComponent component;
        private final Queue<Color> clut = new LinkedList<Color>();

        public Flash(JComponent component) {
            this.component = component;
            for (int i = 0; i < N; i++) {
                clut.add(Color.getHSBColor(1, 1 - (i / N), 1));
            }
            for (int i = 0; i < N; i++) {
                clut.add(Color.getHSBColor(1, i / N, 1));
            }
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            component.setBackground(clut.peek());
            clut.add(clut.remove());
        }
    }

    static public void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.add(new FlashTest());
                f.pack();
                f.setVisible(true);
            }
        });
    }
}
trashgod