Arquivo da categoria: Programação

Dicas de programação, desenvolvimento de software, linguagens de programação

Como criar animações

import java.applet.Applet;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class AppletAnimation extends Applet implements Runnable {
int frameNumber = -1;

int delay = 100;

Thread animatorThread;

boolean frozen = false;

public void init() {
String str;
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if (frozen) {
frozen = false;
start();
else {
frozen = true;
stop();
}
}
});
}

public void start() {
if (!frozen) {
if (animatorThread == null) {
animatorThread = new Thread(this);
}
animatorThread.start();
}
}

public void stop() {
animatorThread = null;
}

public void run() {
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);

long startTime = System.currentTimeMillis();

Thread currentThread = Thread.currentThread();

while (currentThread == animatorThread) {
frameNumber++;

repaint();

try {
startTime += delay;
Thread.sleep(100);
catch (InterruptedException e) {
break;
}
}
}

public void paint(Graphics g) {
g.drawString("Frame " + frameNumber, 0, 30);
}
}

Como criar animações: Paint e Thread

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Insets;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.JFrame;

public class Animate extends JFrame {

private static int DELAY = 100;

Insets insets;

Color colors[] = { Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN,
Color.BLUE, Color.MAGENTA };

public void paint(Graphics g) {
super.paint(g);
if (insets == null) {
insets = getInsets();
}
// Calculate each time in case of resize
int x = insets.left;
int y = insets.top;
int width = getWidth() - insets.left - insets.right;
int height = getHeight() - insets.top - insets.bottom;
int start = 0;
int steps = colors.length;
int stepSize = 360 / steps;
synchronized (colors) {
for (int i = 0; i < steps; i++) {
g.setColor(colors[i]);
g.fillArc(x, y, width, height, start, stepSize);
start += stepSize;
}
}
}

public void go() {
TimerTask task = new TimerTask() {
public void run() {
Color c = colors[0];
synchronized (colors) {
System.arraycopy(colors, 1, colors, 0, colors.length - 1);
colors[colors.length - 1] = c;
}
repaint();
}
};
Timer timer = new Timer();
timer.schedule(task, 0, DELAY);
}

public static void main(String args[]) {
Animate f = new Animate();
f.setSize(200, 200);
f.show();
f.go();
}
}

ADO – Localizando informações

Quando falamos a nível de dados (campos e registros), estamos tratando com o objeto Recordset. Vamos mostrar como encontrar dados específicos em um Recordset ADO. Lembrando que um objeto Recordset possui muitas funções úteis. Entre elas podemos citar as mais usadas: Bookmark, Find, Seek, Filter.

Usando Bookmarks (marcadores)

Um bookmark de um recordset é como um cursor que aponta para um registro específico dentro do Recordset identificando-o de forma única. Fazendo uma analogia: ao ler um livro, você costuma usar um marcador para indicar em qual página parou para, quando retornar a leitura, localizar com rapidez onde parou. Assim funciona um bookmark. Para usá-lo em um objeto recordset, as etapas são:

  • Defina uma variável para ser usada como marcador:  Dim marcador as variant
  • Quando desejar marcar uma posição em um recordset no registro atual usando a variável definida acima, faça:  marcador = rs.bookmark
  • Para retornar a posição marcada no item anterior, faça:  rs.bookmark = marcador

Mas tome cuidado pois nem todos os registros suportam bookmarks. Para verificar se um recordset suporta bookmarks, use a seguinte instrução:  blnmarcador = rs.Supports(adBookmark)

Assim, o método Supports usando o argumento adBookmark retorna TRUE se o recordset suporta bookmarks e FALSE, caso não suporte.

Localizando dados com ADO

Basicamente temos dois métodos para localizar dados em um recordset usando ADO: Find e Seek.

1) Usando o método Find

O método Find é usado para encontrar um registro que contém um determinado valor em um determinado campo do registro. Você define um critério de busca, e se o critério for satisfeito, o ponteiro do registro se posiciona no registro que atendeu ao critério. Se o critério não foi atendido, o ponteiro se posiciona no fim do recordset. A sintaxe é a seguinte:

Find (critério, SkipRows, searchDirection, start)

Parâmetros:

critério – uma string contendo o nome da coluna, o operador de comparação e o valor que desejamos localizar.

Exemplos de strings de busca:

  • “FornecedorID >= 7”
  • “DataPedido = #09/10/1997#”
  • “Codigo > 7”
  • “Nome = ‘” & variavel & “‘”

Lembrando que os valores strings devem vir entre aspas simples (‘Joao’) e as datas devem estar iniciadas e terminadas com o símbolo (#).

SkipRows – define o deslocamento da linha atual ou o bookmark padrão para iniciar a busca. O padrão é começar na linha atual e terminar na última linha.

searchDirection – indica a direção em que o recordset é procurado. Os valores podem ser:

  • adSearchForward ou adSearchBackward – a busca irá cessar no início ou no fim do recordset dependendo destes valores. Se a busca é iniciada para frente e nada for encontrado, o cursor do recordset é definido para além do último registro e a propriedade EOF (End Of File) retorna TRUE. Já se a busca é feita para trás e nada for achado, o cursor é definido para além do início do arquivo e a propriedade BOF (Beginning Of File) retorna TRUE.

start – define um bookmark de início para a busca.

Obs.: Se você não definir a posição do cursor na linha atual quando for iniciar a busca, irá ocorrer um erro. Por isso, antes de usar o método Find, você pode mover o cursor para o início do arquivo usando o método MoveFirst.

Exemplo prático:

Vamos mostrar em um exemplo prático como usar o método Find.

  • Inicie um novo projeto no VB e antes de qualquer coisa, faça uma referência a biblioteca ADO, na opção do menu Project | References, como na figura abaixo.

ado_sek1

  • A seguir, insira o seguinte código no projeto:
Dim cnn As New ADODB.connection
Dim rst As New ADODB.Recordset

Private Sub Form_Load()
Dim criterio As String ‘Abre a conexão
cnn.Open “Provider=Microsoft.Jet.OLEDB.3.51;Data Source=C:testeNorthwind.mdb;” ‘Abre o Recordset
rst.CursorLocation = adUseClient
rst.Open “Select * From Suppliers”, cnn, adOpenKeyset, adLockOptimistic, adCmdText
‘move-se para o primeiro registro
rst.MoveFirst’define o criterio para busca
criterio = “Country Like ‘A%'”
inicia busca no recordset
rst.Find criterio, 0, adSearchForward

‘ percorre o recordset ate o seu final
While Not rst.EOF
Debug.Print rs(“CompanyName”)
marcador = rst.Bookmark
rs.Find criterio, 1, adSearchForward, marcador
Wend

End Sub

Vamos explicar passo a passo:

1. Dim cnn As New ADODB.connection
Dim rst As New ADODB.Recordset

Define as variáveis objetos usadas para a conexão e para o objeto Recordset.

2. ‘Abre a conexão
cnn.Open “Provider=Microsoft.Jet.OLEDB.3.51;Data Source=C:testeNorthwind.mdb;”

Abrimos uma conexão usando o provedor (Microsoft.Jet.OLEDB.3.51) e o Data Source (C:testeNorthwind.mdb).

3. ‘Abre o Recordset
rst.CursorLocation = adUseClient
rst.Open “Select * From Suppliers”, cnn, adOpenKeyset, adLockOptimistic, adCmdText

Definimos o tipo de cursor usado, no caso usamos o cursor do lado do cliente (AdUseClient) e abrimos um recordset com os parâmetros AdOpenKeySet (permite a alteração) e adLockOptimistic (usa o bloqueio pessimista (mantém o bloqueio até usar o método para atualizar)).

4. define o criterio para busca
criterio = “Country Like ‘A%'”
inicia busca no recordset
rst.Find criterio, 0, adSearchForward

Definimos o critério para busca e iniciamos a busca usando o método Find, usando os parâmetros SkipRows = 0 e adSearchForward (busca do início para o fim).

5. While Not rst.EOF
Debug.Print rs(“CompanyName”)
marcador = rst.Bookmark
rs.Find criterio, 1, adSearchForward, marcador
Wend

Percorremos o recordset, imprimindo o campo CompanyName e se posicionando a partir do bookmark anterior, com avanço de um registro para frente, a partir do bookmark (marcador). Note que usamos o bookmark para armazenar a posição atual do registro e usamos esta posição inicial para a próxima busca.

2) Usando o método Seek

O método Seek permite a procura em uma coluna. Ele só encontra os valores iguais ao valor da procura e vai precisar de um provedor de dados que permita a utilização da propriedade Index e o método Seek (nem todos os provedores permitem). Além disso, o método Seek vai requerer um cursor do lado do servidor.

Atualmente, somente alguns provedores permitem usar a propriedade Index e o método Seek do objeto Recordset para procurar por valores em um índice de uma tabela. O provedor OLE DB (Provider for Microsoft Jet 4.0) que é usado para se conectar a um banco de dados Access, permite a utilização do método Seek.

Para verificar se o provedor suporta a propriedade Index e o método Seek, podemos usar o método Supports com os parâmetros adIndex e adSeek. Veja o exemplo abaixo:

If rs.Supports(adIndex) then
msgbox “Este Provedor suporta a propriedade Index”
endif
If rs.Supports(adSeek) then
msgbox “Este Provedor suporta a propriedade Seek”
endif

Você deve ter o cuidado de definir a propriedade Index assim que o Recordset for aberto para depois usar o método Seek. A propriedade Index indica o nome do índice que estará ativo. Assim, supondo que você possua uma tabela chamada clientes e que queira fazer uma busca pela coluna Nome da tabela, vai precisar definir um índice para estar coluna na tabela, dando a ele um nome. O nome do índice pode ser o mesmo nome da coluna. Para o nosso caso, poderíamos ter criado um índice chamado Nome (você poderia ter usado qualquer outro nome para definir o índice). Teríamos então:  rs.index – “nome”

Em muitos casos, quando você usa um campo autonumeração no Access e define este campo como uma chave primária, o índice PrimaryKey será criado para esta coluna da tabela. Então, se for usar esta coluna para fazer uma busca usando o Seek, deverá usar a sintaxe:  rs.Index = “PrimaryKey”

Depois que a propriedade Index foi definida para o nome do índice existente na tabela, podemos usar o método Seek para procurar na coluna desejada. Quando o método Seek encontrar o registro desejado, o ponteiro irá se posicionar neste registro. Se nada for encontrado, o ponteiro é definido para EOF. A sintaxe é a seguinte:

rs.Seek Array(valordacoluna)

Aqui você deve tomar cuidado. Como um índice pode ser constituído de uma ou mais colunas, o termo valordacoluna indica os valores da coluna. Vamos supor que você tem uma tabela de clientes com um campo CodigoID definido como chave primária, e você quer procurar pelo cliente cujo código seja igual a 120. Você deverá procurar pelo valor 120 na coluna CodigoID e deverá fazer:

rs.Index = “PrimaryKey”

rs.Seek Array(120)

Se o índice possuir mais de uma coluna, você deverá informar no vetor (array) os valores de todas as colunas contidas no índice. Por exemplo, se uma tabela pedidos possuir um índice chamado PrimaryKey e for constituído pelos campos codigopedido e codigoproduto da tabela, ao usar o método Seek para procurar pelo pedido cujo código seja igual a 23 e código de produto igual a 50, você deverá fazer:

rs.Index = “PrimaryKey”

rs.Seek Array(23,50)

Vejamos agora um exemplo completo usando a propriedade Index e o método Seek:

Neste exemplo, usaremos o banco de dados Northwind.mdb e a tabela Funcionários. A estrutura e os índices criados são dados abaixo:

Iremos usar o índice chave primária CodigoDoFuncionario para localizar o funcionário e exibir o seu nome.

O projeto usará um formulário, uma caixa de texto e um botão de comando.

Defina as variáveis objeto na seção General Declarations:

Dim cnn As New ADODB.connection
Dim rst As New ADODB.Recordset

O código do botão de comando segue abaixo:

Private Sub Command1_Click()

If Text1.Text = “” Then
MsgBox ” Informe um valor para busca ”
Exit Sub
End If
‘Abre a conexão
cnn.Open “Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:testeNorthwind.mdb;”Abre o Recordset
rst.CursorLocation = adUseServer
rst.Open “Funcionários”, cnn, adOpenKeyset, adLockReadOnly, adCmdTableDirect

If rst.Supports(adIndex) And rst.Supports(adSeek) Then
rst.Index = “CódigoDoFuncionário”
rst.MoveFirst
rst.Seek Array(CLng(Text1.Text))
If rst.EOF Then
MsgBox “Funcionário não localizado”
Else
MsgBox rst(“CódigoDoFuncionário”) & ” – ” & rst(“nome”) & vbCrLf
End If
Else
MsgBox ” O provedor utilizado não suporta : Index e Seek ”
End If

´Fechamos a conexão e o recordset
rst.Close
cnn.Close
Set rs = Nothing
Set cnn = Nothing

End Sub

Observe que antes de iniciar a busca, verificamos se o provedor suporta a utilização de Index e de Seek. Se o método Supports é novo para você, veja abaixo as constantes que você pode usar com ele:

Constante Utilização
adAddNew Verifica se novos registros podem ser adicionados
adApproxPosition Verifica se as propriedades: AbsolutePage e AbsolutePosition estão disponíveis
adBookMark Verifica se podemos usar um marcador no Recordset
adDelete Verifica se os registros poderão ser excluídos
AdHoldRecords Verifica se podemos recuperar os registros sem submeter as alterações
adResync Verifica se o método Resynd esta disponível
adUpdate Verifica se o conjunto de registros permite a atualização
adUpdateBatch Verifica se o recordset permite a atualização em lote – via UpdateBatch

Noise Image

import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.IndexColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.util.Random;

import javax.swing.JComponent;
import javax.swing.JFrame;

public class StaticGenerator extends JComponent implements Runnable {
byte[] data;

BufferedImage image;

Random random;

public void initialize() {
int w = getSize().width, h = getSize().height;
int length = ((w + 7) * h) / 8;
data = new byte[length];
DataBuffer db = new DataBufferByte(data, length);
WritableRaster wr = Raster.createPackedRaster(db, w, h, 1, null);
ColorModel cm = new IndexColorModel(1, 2, new byte[] { (byte) 0, (byte) 255 }, new byte[] {
(byte) 0, (byte) 255 }, new byte[] { (byte) 0, (byte) 255 });
image = new BufferedImage(cm, wr, false, null);
random = new Random();
new Thread(this).start();
}

public void run() {
while (true) {
random.nextBytes(data);
repaint();
try {
Thread.sleep(1000 / 24);
catch (InterruptedException e) { /* die */
}
}
}

public void paint(Graphics g) {
if (image == null)
initialize();
g.drawImage(image, 0, 0, this);
}

public static void main(String[] args) {
JFrame f = new JFrame();
f.add(new StaticGenerator());
f.setSize(300, 300);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}

Hypnosis animation

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.GeneralPath;

import javax.swing.JComponent;
import javax.swing.JFrame;

public class Hypnosis1 extends JComponent implements Runnable {
private int[] coordinates;

private int[] deltas;

private Paint paint;

public Hypnosis1(int numberOfSegments) {
int numberOfCoordinates = numberOfSegments * 4 + 2;
coordinates = new int[numberOfCoordinates];
deltas = new int[numberOfCoordinates];
for (int i = 0; i < numberOfCoordinates; i++) {
coordinates[i] = (int) (Math.random() * 300);
deltas[i] = (int) (Math.random() * 4 + 3);
if (deltas[i] > 4)
deltas[i] = -(deltas[i] - 3);
}
paint = new GradientPaint(0, 0, Color.blue, 20, 10, Color.red, true);

Thread t = new Thread(this);
t.start();
}

public void run() {
try {
while (true) {
timeStep();
repaint();
Thread.sleep(1000 / 24);
}
catch (InterruptedException ie) {
}
}

public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Shape s = createShape();
g2.setPaint(paint);
g2.fill(s);
g2.setPaint(Color.white);
g2.draw(s);
}

private void timeStep() {
Dimension d = getSize();
if (d.width == 0 || d.height == 0)
return;
for (int i = 0; i < coordinates.length; i++) {
coordinates[i] += deltas[i];
int limit = (i % 2 == 0) ? d.width : d.height;
if (coordinates[i] < 0) {
coordinates[i] = 0;
deltas[i] = -deltas[i];
else if (coordinates[i] > limit) {
coordinates[i] = limit - 1;
deltas[i] = -deltas[i];
}
}
}

private Shape createShape() {
GeneralPath path = new GeneralPath();
path.moveTo(coordinates[0], coordinates[1]);
for (int i = 2; i < coordinates.length; i += 4)
path.quadTo(coordinates[i], coordinates[i + 1], coordinates[i + 2], coordinates[i + 3]);
path.closePath();
return path;
}

public static void main(String[] args) {
JFrame f = new JFrame("Hypnosis");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new Hypnosis1(4));
f.setSize(300, 300);
f.setVisible(true);
}
}

Font size animation

import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class FontSizeAnimation extends JPanel implements ActionListener {
Timer timer;
int x = 1;
float alpha = 1;

public FontSizeAnimation() {
timer = new Timer(8, this);
timer.setInitialDelay(190);
timer.start();
}

public void paint(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;

Font font = new Font("Dialog", Font.PLAIN, x);
g2d.setFont(font);

FontMetrics fm = g2d.getFontMetrics();
String s = "Java";

int w = (int) getSize().getWidth();
int h = (int) getSize().getHeight();

int stringWidth = fm.stringWidth(s);

g2d.drawString(s, (w - stringWidth) / 2, h / 2);
}

public static void main(String[] args) {
JFrame frame = new JFrame("FontSizeAnimation");
frame.add(new FontSizeAnimation());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

public void actionPerformed(ActionEvent e) {
x += 1;
alpha -= 0.0001;
repaint();
}
}

Fade out de uma imagem: a imagem vai ficando transparente gradualmente até que esteja completamente invisível

import java.awt.AlphaComposite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class FadeOutImage extends JPanel implements ActionListener {
Image myImage = new ImageIcon("a.jpg").getImage();

Timer timer = new Timer(20, this);

private float alpha = 1f;

public FadeOutImage() {
timer.start();
}

public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;

g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
g2d.drawImage(myImage, 10, 10, null);
}

public void actionPerformed(ActionEvent e) {
alpha += -0.01f;
if (alpha <= 0) {
alpha = 0;
timer.stop();
}
repaint();
}
public static void main(String[] args) {
JFrame frame = new JFrame("Fade out");
frame.add(new FadeOutImage());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 250);
frame.setVisible(true);
}

}

A rotating and scaling rectangle

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class SwingTimerBasedAnimationScaleRotate extends JPanel implements ActionListener {
Timer timer;
private double angle = 0;
private double scale = 1;
private double delta = 0.01;
Rectangle.Float r = new Rectangle.Float(20, 20, 200, 200);
public SwingTimerBasedAnimationScaleRotate() {
timer = new Timer(10, this);
timer.start();
}

public void paint(Graphics g) {
int h = getHeight();
int w = getWidth();

Graphics2D g2d = (Graphics2D) g;

g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

g2d.translate(w / 2, h / 2);
g2d.rotate(angle);
g2d.scale(scale, scale);

g2d.fill(r);
}

public static void main(String[] args) {

JFrame frame = new JFrame("Moving star");
frame.add(new SwingTimerBasedAnimationScaleRotate());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(420, 250);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

public void actionPerformed(ActionEvent e) {

if (scale < 0.01) {
delta = -delta;
else if (scale > 0.99) {
delta = -delta;
}

scale += delta;
angle += 0.01;

repaint();
}
}

Timer based animation

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class TimerBasedAnimation extends JPanel implements ActionListener {
private Ellipse2D.Float ellipse = new Ellipse2D.Float();

private double esize;

private double maxSize = 0;

private boolean initialize = true;

Timer timer;

ActionListener updateProBar;

public TimerBasedAnimation() {
setXY(20 * Math.random(), 200, 200);

timer = new Timer(20, this);
timer.setInitialDelay(190);
timer.start();
}

public void setXY(double size, int w, int h) {
esize = size;
ellipse.setFrame(10, 10, size, size);
}

public void reset(int w, int h) {
maxSize = w / 10;
setXY(maxSize * Math.random(), w, h);
}

public void step(int w, int h) {
esize++;
if (esize > maxSize) {
setXY(1, w, h);
else {
ellipse.setFrame(ellipse.getX(), ellipse.getY(), esize, esize);
}
}

public void render(int w, int h, Graphics2D g2) {
g2.setColor(Color.BLUE);
g2.draw(ellipse);
}

public void paint(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;

RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);

rh.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

g2.setRenderingHints(rh);
Dimension size = getSize();

if (initialize) {
reset(size.width, size.height);
initialize = false;
}
this.step(size.width, size.height);
render(size.width, size.height, g2);
}

public void actionPerformed(ActionEvent e) {
repaint();
}

public static void main(String[] args) {
JFrame frame = new JFrame("TimerBasedAnimation");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TimerBasedAnimation());
frame.setSize(350, 250);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

Is Event Dispatcher Thread

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.AbstractAction;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;

public class IsEDTExample extends JPanel {
private boolean keepRunning;

private static int RED = 0;

private static int BLUE = 1;

private static int GREEN = 2;

private static int VARIABLE = 3;

private static int SIZE = 3;

private int threadShade;

private ColorTableModel tableModel= new ColorTableModel();

private Thread colorShadeThread;

public IsEDTExample() {
JTable table = new JTable(tableModel);
table.setRowHeight(100);
table.setDefaultRenderer(Object.class, new ColorRenderer());
add(table);

add(new JLabel("Thread Color Shade:"));
ButtonGroup group = new ButtonGroup();
JRadioButton redOption = new JRadioButton("Red");
group.add(redOption);
redOption.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
threadShade = RED;
}
});

JRadioButton blueOption = new JRadioButton("Blue");
group.add(blueOption);
blueOption.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
threadShade = BLUE;
}
});

JRadioButton greenOption = new JRadioButton("Green");
group.add(greenOption);
greenOption.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
threadShade = GREEN;
}
});

redOption.setSelected(true);
this.threadShade = RED;

add(redOption);
add(greenOption);
add(blueOption);

add(new JButton(new RandomColorAction()));

this.keepRunning = true;
this.colorShadeThread = new Thread(new RandomColorShadeRunnable());
this.colorShadeThread.start();
}

private class RandomColorAction extends AbstractAction {
public RandomColorAction() {
super("Create Random Color");
}

public void actionPerformed(ActionEvent e) {
IsEDTExample.this.tableModel.generateRandomColor(VARIABLE);
}
}

private class ColorTableModel extends AbstractTableModel {
private Color[][] colors = new Color[3][3];

public ColorTableModel() {
for (int i = 0; i < SIZE; i++) {
for (int x = 0; x < SIZE; x++) {
colors[i][x] = Color.white;
}
}
}

public int getRowCount() {
return SIZE;
}

public int getColumnCount() {
return SIZE;
}

public Object getValueAt(int rowIndex, int columnIndex) {
return colors[rowIndex][columnIndex];
}

public void generateRandomColor(int type) {
Random random = new Random(System.currentTimeMillis());
final int row = random.nextInt(SIZE);
final int column = random.nextInt(SIZE);
final Color color;
if (type == RED) {
color = new Color(random.nextInt(256), 0, 0);
else if (type == BLUE) {
color = new Color(0, 0, random.nextInt(256));
else if (type == GREEN) {
color = new Color(0, random.nextInt(256), 0);
else {
color = new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256));
}

if (SwingUtilities.isEventDispatchThread()) {
colors[row][column] = color;
fireTableCellUpdated(row, column);
else {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
colors[row][column] = color;
fireTableCellUpdated(row, column);
}
});
}
}
}

private class ColorRenderer implements TableCellRenderer {
private JLabel label;

public ColorRenderer() {
label = new JLabel();
label.setOpaque(true);
label.setPreferredSize(new Dimension(100, 100));
}

public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
label.setBackground((Color) value);
return label;
}
}

private class RandomColorShadeRunnable implements Runnable {
public void run() {
while (keepRunning) {
tableModel.generateRandomColor(threadShade);
try {
Thread.sleep(500);
catch (InterruptedException e) {
}
}
}
}

public static void main(String[] a) {
JFrame f = new JFrame("Is Event Dispatch Thread Example");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new IsEDTExample());
f.pack();
f.setVisible(true);
}

}