Il timer Javax.swing si ripete bene, ma ActionListener non fa nulla

Sto provando a far lampeggiare il colore di sfondo in un campo di testo. La mia configurazione del timer è la seguente:

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

Il mio actionListener è il seguente:

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

Ora, quando inserisco questo in debug e seguo l’azione, il programma fa ripetutamente il passaggio al flash e fa passare tra le due alternative. Ma sullo schermo, si verifica solo il primo interruttore. Dopo di ciò, nessuna azione, sebbene il flash funzioni ancora.

Cosa c’è di sbagliato qui?

Grazie in anticipo per qualsiasi aiuto.

Ci sono un paio di problemi qui.

La prima cosa ovvia è che sembra che tu stia usando la statica mutevole. Questa è una pessima idea e indica (e provoca!) Confusione. In questo caso particolare, uno dei problemi causati è che il flasher statico è condiviso.

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

Stiamo aggiungendo due azioni Flash . Normalmente questo sarebbe male, ma solo produrre un “bug” non rilevabile. Il colore verrebbe impostato due volte.

Metti insieme queste due cose e abbiamo due azioni senza interruzione che eseguono lo stesso interruttore. Due levette. Lo stato non cambia (sebbene ci siano ridipinture, eventi di modifica delle proprietà, ecc.).

Quindi, non utilizzare statiche modificabili e mantenere il codice pulito.

Questo esempio varia continuamente la saturazione del colore di sfondo di un pannello:

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 clut = new LinkedList(); 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); } }); } } 
 tmr = new javax.swing.Timer(1000, flash); 

Ho provato il tuo codice e funziona bene.

Perché usi un contesto statico per SpreademPanel.historyPnl.NameTxt ?

MODIFICARE

Potresti voler ridisegnare la tua class per passare il componente nel costruttore.

 private class Flash implements ActionListener { private boolean flasher = false; private JComponent component; public Flash(JComponent component) { this.component = component; } public void actionPerformsd(ActionEvent evt) { if (flasher) { component.setBackground(Color.white); } else { component.setBackground(Color.pink); } flasher = !flasher; } //actionPerformsd } //Flash 

e poi inizialo con

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