12 de agosto de 2008

Criar um relógio digital utilizando SWT.

Olá galeraaaa...

Essa é a minha estréia aqui no Java Anywhere. Minhas postagens vão parecer no mínimo interessantes...pois dificilmente irei abordar temas avançados de Java, mas principalmente aqueles que parecem ser mais básicos...que todos acham que sabem...mas sempre fica alguma dúvida. Principalmente para quem está começando na área.
Bom, vamos falar de interface gráfica, mais especificamente o SWT. Atualmente eu trabalho única e exclusivamente com SWT. Porque o SWT e não o Swing? O SWT é "portável". Roda em qualquer plataforma. É preciso adaptá-lo ao sistema operacional, mas ainda assim ele é vantajoso. É bonito e tem algumas particularidades que facilitam para nós desenvolvedores, e outras que nos deixam com mais cabelos brancos.
Eu precisei desenvolver um relógio digital que deveria aparecer em uma tela de agendamento de consultas. Não seria nenhuma novidade, afinal, existem vários exemplos de relógios digitais na Web, mas, todos em Swing. Aí começa o problema. O SWT tem a sua própria metodologia para o uso de Threads. Aliás, ele tem a sua própria Thread, se me permitem afirmar. E como compreender isso? Eu procurei muito. Fiz várias perguntas no GUJ...mas ninguém sabia responder, até um amigo meu de trabalho me mostrar como é que se trabalha com Threads em SWT (Valeu Charles).
Bem, vamos lá. Vamos criar o nosso relógio digital.

Em primeiro lugar é importante que você já tenha o seu Eclipse com o devido Visual Editor e as Libs do SWT.

Primeiro passo: Construa uma Visual Classe chamada Relogio. Deixe como composite e mantenha o método main assinalado.

Nesse momento sua classe estará assim:

import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;

public class Relogio extends Composite {



    public Relogio(Composite parent, int style) {
        super(parent, style);
        initialize();
    }

    private void initialize() {
        setSize(new Point(300, 135));
        //setLayout(new GridLayout());
    }
    /**
    * @param args
    */
    public static void main(String[] args) {
        Display display = Display.getDefault();
        Shell shell = new Shell(display);
        shell.setLayout(new FillLayout());
        shell.setSize(new Point(300, 135));
        new Relogio(shell, SWT.NONE);
        shell.open();

        while (!shell.isDisposed()) {
            if (!display.readAndDispatch())
                display.sleep();
            }
        display.dispose();
    }
}

Você vai perceber que não estou utilizando o GridLayout, como o próprio Eclipse já sugere. Comente e trabalhe sem o Grid por hora.
Agora, o próximo passo é você criar duas Labels. Nomeie uma como labelData e a outra como labelHora.

Nesse momento você terá algo desse tipo:

labelData = new Label(this, SWT.NONE);
labelData.setBounds(new Rectangle(45, 60, 100, 30));
labelData.setText("");

labelHora = new Label(this, SWT.NONE);
labelHora.setBounds(new Rectangle(165, 60, 100, 30));
labelHora.setText("");
this.setSize(new Point(300, 135));
//Comente aqui//
//setLayout(new GridLayout());
}

Eu procurei ajustar a tela ao meu gosto sem seguir nenhum padrão pelo simples fato de se tratar de apenas uma demonstração.
Agora...pra deixar nossa classe bem organizada, vamos declarar a fonte assim como o tamanho do texto como atributos "private".Em seguida, dentro do construtor e antes de chamar o método initialize() adicionaremos aos atributos o tamanho e a fonte do texto.
Essa mesma variável nós usaremos agora lá no nosso Label assim como mostra o exemplo. parece que estou dando voltas não é ? Mas para quem faz manutenção esse tipo de organização ajuda muito.

public class Relogio extends Composite {

    private Label labelData = null;
    private Label labelHora = null;
    private Font fontVerdanaDataBold = null;
    private Font fontVerdanaHoraBold = null;

    public Relogio(Composite parent, int style) {
        super(parent, style);
        //Aqui declaramos como queremos o nosso texto//
        this.fontVerdanaDataBold = new Font(getDisplay(), "Verdana", 12, SWT.BOLD);
        this.fontVerdanaHoraBold = new Font(getDisplay(), "Verdana", 12, SWT.BOLD);
        initialize();
    
    private void initialize() {
        labelData = new Label(this, SWT.NONE);
        labelData.setBounds(new Rectangle(45, 60, 100, 30));
        //Aqui declaramos a variável com tamanho e fonte do texto//
        labelData.setFont(fontVerdanaDataBold);
        labelData.setText("");
        labelHora = new Label(this, SWT.NONE);
        labelHora.setBounds(new Rectangle(165, 60, 100, 30));
        //Aqui declaramos a variável com tamanho e fonte do texto//
        labelData.setFont(fontVerdanaHoraBold);
        labelHora.setText("");
        this.setSize(new Point(300, 135));
        //comente essa linha//
        //setLayout(new GridLayout());
    }
    }
Agora, vamos a parte mais gostosa do bolo. A criação desse relógio.
Bem abaixo da linha " labelHora.setText("")" iremos criar uma Thread. Essa é aquela que conhecemos. Não tem segredo algum. Logo em seguida criamos as variáveis de conversão de data e hora, não devemos esquecer dos "imports" e não esquecer de usar "data" do pacote javaUtil no "import". Mas e essa tal Thread do SWT?
Ela está lá dentro. Logo abaixo das variáveis de data e hora. Ela se chama "asyncExec". Sem ela, o relógio não funcionaria.
O código ficará assim:

(new Thread(new Runnable() {
    SimpleDateFormat sdfData = new SimpleDateFormat("dd/MM/yyyy");
    SimpleDateFormat sdfHora = new SimpleDateFormat("HH:mm:ss");

    public void run() {
        while (true) {
            if (!isDisposed() && !getDisplay().isDisposed()) {
                //Aqui chamamos a tal "Thread" do SWT///
                getDisplay().asyncExec(new Runnable() {
                public void run() {
                    if (!labelData.isDisposed()&& !labelHora.isDisposed()) {
                        Date data = new Date();
                        labelData.setText(sdfData.format(data));
                        labelHora.setText(sdfHora.format(data));
                    }
                }
            });
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
           }
        } else {
            break;
        }
    
 }

})).start();

De mais é tudo Java básico. Vale a pena fazer o teste em casa. Fica muito bacana.Não esqueçam de ajustar o tamanho da tela também no "método main" ok?
Boa sorte galera. Espero ter ajudado.

3 comentários:

Anônimo disse...

Parabéns, Arthur. Tenho procurado material sobre SWT também pq não gosto de SWING; acho muito feio. Arthur, onde eu consigo as bibliotecas SWT? Acho que tá faltando isso na postagem.

Anônimo disse...

Olá Rafael. O site do eclipse pode te fornecer todas as libs...mas se quiser se aprofundar acompanhe o nebula.org...pois eles sempre tem muita coisa bacana. Se estiver iniciando eu recomendo o livro "Dominando o Eclipse". Tem muita coisa interessante sobre SWT, fora que te explica como configurar o Visual Editor e tudo mais.
Boa sorte.

Romario disse...

olá galera visitem o meu blog:

Romariosite.blogspot.com