I don't think that having two Timer
instances is the way to go. The Swing Timer
is notorious for 'drifting' away from the perfect beat over time.
Better to create a single timer with the logic needed to control all actions.
E.G. Showing the allowable moves for a Chess Knight.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class KnightMove {
KnightMove() {
initUI();
}
ActionListener animationListener = new ActionListener() {
int blinkingState = 0;
@Override
public void actionPerformed(ActionEvent e) {
final int i = blinkingState % 4;
chessSquares[7][1].setText("");
chessSquares[5][0].setText("");
chessSquares[5][2].setText("");
switch (i) {
case 0:
setPiece(chessSquares[5][0], WHITE + KNIGHT);
break;
case 1:
case 3:
setPiece(chessSquares[7][1], WHITE + KNIGHT);
break;
case 2:
setPiece(chessSquares[5][2], WHITE + KNIGHT);
}
blinkingState++;
}
};
public void initUI() {
if (ui != null) {
return;
}
ui = new JPanel(new GridLayout(8, 8));
ui.setBorder(new CompoundBorder(new EmptyBorder(4, 4, 4, 4),
new LineBorder(Color.BLACK,2)));
boolean black = false;
for (int r = 0; r < 8; r++) {
for (int c = 0; c < 8; c++) {
JLabel l = getColoredLabel(black);
chessSquares[r][c] = l;
ui.add(l);
black = !black;
}
black = !black;
}
for (int c = 0; c < 8; c++) {
setPiece(chessSquares[0][c], BLACK + STARTING_ROW[c]);
setPiece(chessSquares[1][c], BLACK + PAWN);
setPiece(chessSquares[6][c], WHITE + PAWN);
setPiece(chessSquares[7][c], WHITE + STARTING_ROW[c]);
}
Timer timer = new Timer(750, animationListener);
timer.start();
}
private void setPiece(JLabel l, int piece) {
l.setText("<html><body style='font-size: 60px;'>&#" + piece + ";");
}
private final JLabel getColoredLabel(boolean black) {
JLabel l = new JLabel();
l.setBorder(new LineBorder(Color.DARK_GRAY));
l.setOpaque(true);
if (black) {
l.setBackground(Color.GRAY);
} else {
l.setBackground(Color.WHITE);
}
return l;
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
KnightMove o = new KnightMove();
JFrame f = new JFrame("Knight Moves");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.setResizable(false);
f.pack();
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
private JComponent ui = null;
JLabel[][] chessSquares = new JLabel[8][8];
public static final int WHITE = 9812, BLACK = 9818;
public static final int KING = 0, QUEEN = 1,
ROOK = 2, KNIGHT = 4, BISHOP = 3, PAWN = 5;
public static final int[] STARTING_ROW = {
ROOK, KNIGHT, BISHOP, KING, QUEEN, BISHOP, KNIGHT, ROOK
};
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…