Таймер Javax.swing повторяется нормально, но ActionListener ничего не делает
Я пытаюсь прошить цвет фона в текстовом поле. Моя настройка таймера выглядит следующим образом:
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 ответа
Здесь есть пара проблем.
Первая очевидная вещь заключается в том, что вы используете изменяемую статику. Это действительно плохая идея и указывает (и вызывает!) Путаницу. В данном конкретном случае одной из проблем является то, что flasher
статический является общим.
Flash flash = new Flash(); //set up timer
tmr = new javax.swing.Timer(1000, new Flash());
tmr.addActionListener(flash);
Мы добавляем два Flash
действия. Обычно это было бы плохо, но просто выявляет необнаружимую "ошибку". Цвет будет установлен дважды.
Соедините эти две вещи вместе, и у нас есть два действия без перерыва, которые выполняют одно и то же переключение. Два переключателя. Состояние не изменяется (хотя есть события перерисовки, изменения свойств и т. Д.).
Так что не используйте изменяемую статику, и держите код в чистоте.
Этот пример постоянно изменяет насыщенность цвета фона панели:
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);
}
});
}
}
Я попробовал ваш код, и он отлично работает.
Почему вы используете статический контекст для SpreademPanel.historyPnl.NameTxt
?
РЕДАКТИРОВАТЬ
Возможно, вы захотите изменить дизайн своего класса, чтобы передать компонент в конструктор.
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();