Таймер Javax.swing повторяется нормально, но ActionListener ничего не делает - PullRequest
4 голосов
/ 23 января 2010

Я пытаюсь прошить цвет фона в текстовом поле. Моя настройка таймера выглядит следующим образом:

 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();                 

Мой actionListener выглядит следующим образом:

 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

Теперь, когда я помещаю это в отладку и следую за действием, программа многократно проходит флэш и переключается между двумя альтернативами. Но на экране только первый переключатель происходит. После этого никаких действий не происходит, хотя вспышка все еще работает.

Что здесь не так?

Заранее спасибо за любую помощь.

Ответы [ 4 ]

6 голосов
/ 23 января 2010

В этом примере постоянно изменяется насыщенность цвета фона панели:

FlashTest

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);
            }
        });
    }
}
4 голосов
/ 23 января 2010

Здесь есть пара проблем.

Первое очевидное, что вы, похоже, используете изменяемую статику. Это действительно плохая идея и указывает (и вызывает!) Путаницу. В данном конкретном случае одной из проблем является то, что статический flasher является общим.

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

Мы добавляем два Flash действия. Обычно это было бы плохо, но просто выявляет необнаружимую «ошибку». Цвет будет установлен дважды.

Соберите эти две вещи вместе, и у нас есть два действия без перерыва, которые выполняют одно и то же переключение. Два переключателя. Состояние не изменяется (хотя есть перерисовки, события изменения свойств и т. Д.).

Так что не используйте изменяемую статику и держите код в чистоте.

3 голосов
/ 23 января 2010
tmr = new javax.swing.Timer(1000, flash);
2 голосов
/ 23 января 2010

Я попробовал ваш код, и он отлично работает.

Почему вы используете статический контекст для SpreademPanel.historyPnl.NameTxt?

EDIT

Возможно, вы захотите изменить класс, чтобы передать компонент в конструктор.

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

и затем инициализируйте его с помощью

 Flash flash = new Flash(SpreademPanel.historyPnl.NameTxt);
 Timer tmr = new javax.swing.Timer(1000, flash);
 tmr.start();
...