Teria como Colocar uma Interface Gráfica nesse Código?!

3 respostas
D

O código referente a um Jogo da Forca com Cliente/Servidor.
Foi utilizado Socket (DatagramSocket).
O Código abaixo é a parte do Cliente.

public class DatagramClient {

    public static void main(String[] args) {
        String hostname;
        int port = 2018;
        int len = 1024;
        DatagramPacket sPacket, rPacket;
        
        if (args.length > 0) {
            hostname = args[0];
        } else {
            hostname = "localhost";
        }
        try {
            InetAddress ia = InetAddress.getByName(hostname);
            DatagramSocket datasocket = new DatagramSocket();
            BufferedReader stdinp = new BufferedReader(
                    new InputStreamReader(System.in));

            while (true) {
                try {

                    // Eu queria, se fosse possível, colocar uma interface, em que
                    // Nessa parte de digitar a letra, na interface teria um campo de texto e um botão enviar.      
                    System.out.print("Digite a Letra: ");
                    String echoline = stdinp.readLine();

                    if (echoline.equals("done")) {
                        break;
                    }

                    String letra = echoline.toLowerCase();

                    // Aqui o que teria digitado no campo texto, seria enviado para o Servidor;
                    // Datagrama enviada para o Servidor.
                    byte[] buffer = new byte[letra.length()];
                    buffer = letra.getBytes();
                    sPacket = new DatagramPacket(
                            buffer,
                            buffer.length,
                            ia,
                            port);
                    datasocket.send(sPacket);

                    // Aqui é a resposta vinda do Servidor, essa resposta seria setada no Text Área da interface;
                    // Datagrama Recebida do Servidor;
                    byte[] rbuffer = new byte[len];
                    rPacket = new DatagramPacket(rbuffer, rbuffer.length);
                    datasocket.receive(rPacket);

                    String retstring = new String(rPacket.getData(),
                            0, rPacket.getLength());

                    ArrayList<String> temp;
                    temp = quebraMsgServidor(retstring);
                    
                    // Toda essa informação seria posta no Text Área.
                    System.out.println("-----------------------------------------");
                    System.out.println("Status do Jogo: " + temp.get(0));
                    System.out.println("Tentativas Restantes: " + temp.get(1));
                    System.out.println("Anagrama: " + temp.get(2));
                    System.out.println("Palavra Secreta: " + temp.get(3) + "\n");
                    desenhoForca(temp.get(1));
                    System.out.println("\n-----------------------------------------");

                    if (temp.get(1).equals("0") || temp.get(0).equals("Parabens! Voce Acertou a Palavra.")) {
                        System.out.println("Fim do Jogo!");
                        System.exit(0);
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }
            } // fim while			
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (SocketException e) {
            e.printStackTrace();
        }
    } // fim main

    // Função para "quebrar"  a string vinda do servidor
    public static ArrayList<String> quebraMsgServidor(String doServidor) {
        ArrayList<String> msg = new ArrayList();
        String[] t;

        t = doServidor.split(Pattern.quote("*"));
        for (int i = 0; i < t.length; i++) {
            msg.add(t[i]);
        }
        return msg;
    }

    // Função para desenhar a Forca, mas com interface será feita através imagens setadas em um Jlabel.
    public static void desenhoForca(String tentativa) {
        int temp = Integer.parseInt(tentativa);
        //String boneco = "";

        switch (temp) {
            case 6: {
                System.out.print("Voce está a Salvo!!");
                break;
            }
            case 5: {
                System.out.println("  ( )");
                break;
            }
            case 4: {
                System.out.println("  ( )");
                System.out.println("   |");
                break;
            }
            case 3: {
                System.out.println("  ( )");
                System.out.println("   |\\");
                break;
            }
            case 2: {
                System.out.println("  ( )");
                System.out.println("  /|\\");
                break;
            }
            case 1: {
                System.out.println("  ( )");
                System.out.println("  /|\\");
                System.out.println("    \\");
                break;
            }
            case 0: {
                System.out.println("  ( )");
                System.out.println("  /|\\");
                System.out.println("  / \\");
                break;
            }
        }
    }
}

O problema, acho, é fazer a interface gráfica que pegue os valos que irão ser digitados dentro do While com um Campo Texto e apos digitado ser enviado por um botão. Mas como está dentro de um While, não sei como fazer isso.

o Funcionamento seria: Usuário Digita a Letra, essa é enviada para o Servidor, esse envia de volta uma resposta que será setada no text área, se descobriu a letra, fim do jogo, se não, deverá digitar uma nova letra… e assim por diante…

Sem interface, só com stdinp.readLine(); é fácil, já está funcionando… Mas queria colocar uma interface para ficar mais amigável e mais interessante.

Se alguém poder passar dicas, soluções ou dizer que não dá pra fazer o que estou tentado seria de grande ajuda!!!
Abraço a Todos e Feliz Natal!!!

3 Respostas

J

Bom dia,

O problema : Mistura de coisas que não tem nada a fazer juntos no While !! utilize Methodos et Classes para Separação de preocupações , "separation of concerns (SoC)" …

O problema é a apresentação (IHM, GUI) misturada com a parte de comunicação (SOCKET) …

Temos que manter o mesmo código, mas criar métodos diferentes no bom lugar e uma classe ViewJogoDaForca com SWING para a camada apresentação

Em JAVA todo (ou quase todo) é possível , quando se pensa não unicamente no código mas  sobretudo na arquitetura e nos testes funcionais.

Algumas regras para resolver o problema :

1- O desenvolvimento pode/deve ser dirigido pela arquitetura e as funcionalidades.

"[b]The development should be driven by the architecture and functionalities[/b]."

2- Separação de preocupações , "separation of concerns (SoC)"

Por exemplo separar a apresentação, e estruturas de dados do processamento de dados e da parte de comunicação ...

3- Utilizando uma metodologia ágil (ler o manifesto ágil) para gerenciamento de projectos como Extreme Programming (XP) associada a SCRUM … Kanban, Lean

Dito de outra maneira não tenham os olhos muito perto do código se não , não podem ver o resto , de outros aspetos muito importantes como por exemplo a arquitetura e as funcionalidades !


Agora vou explicar como resolver este caso :

1- Arquitetura : Para resolver o caso vou separar o camada apresentação (GUI, IHM) e da parte de comunicação

2- As funcionalidades vistas a través da IHM ou seja a GUI

Numa classe Java nomeada por exemplo  ViewJogoDaForca criar no construtor da classe : JFrame ,  JTextField, JButton, JTextArea
Vamos agora criar um JPanel para o ContentPane da JFrame associado a um BorderLayout
depois criar um JPanel associado a um  FlowLayout no qual vamos meter o JTextField, JButton botão enviar e metemos este JPanel ao norte no JPanel previamente construído.

O JTextArea pode ser metido no "Center" do BorderLayout e o JLabel no South do BorderLayout para desenhar a Forca, com interface será feita através imagens setadas nesse JLabel.

Agora falta apenas usar a técnica para gerências famosos eventos do botão. Técnica das classes internas locais anónimas.
(quando se faz um click no botão faz um apelo a um método que recupera o texto contido no JTextField e envia na rede dos SOCKET …

Quando o servidor responde o JTextArea exibe o texto enviada pelo servidor

Resultado a GUI : consiste em um campo de texto e um botão para o norte e para o sul a área de exibição de texto (JTextArea).

3- Parte de comunicação

Solução :  separar a  exibição do menu e a parte de comunicação
                 -----&gt;  Temos que manter o mesmo código, mas criar métodos diferentes no bom lugar.
                  ----&gt;   O while  devia servir para o menu apresentação num método especial par esse efeito

Experimente estas dicas e se não conseguir sozinho envia massagem para explicar mais como resolver este problema de concepção de programas OO.

Porque aquele que encontra sem buscar há muito tempo busca sem encontrar !

Best regards !

D

JxtaNode:
Bom dia,

O problema : Mistura de coisas que não tem nada a fazer juntos no While !! utilize Methodos et Classes para Separação de preocupações , "separation of concerns (SoC)" …

O problema é a apresentação (IHM, GUI) misturada com a parte de comunicação (SOCKET) …

Temos que manter o mesmo código, mas criar métodos diferentes no bom lugar e uma classe ViewJogoDaForca com SWING para a camada apresentação

Em JAVA todo (ou quase todo) é possível , quando se pensa não unicamente no código mas  sobretudo na arquitetura e nos testes funcionais.

Algumas regras para resolver o problema :

1- O desenvolvimento pode/deve ser dirigido pela arquitetura e as funcionalidades.

"[b]The development should be driven by the architecture and functionalities[/b]."

2- Separação de preocupações , "separation of concerns (SoC)"

Por exemplo separar a apresentação, e estruturas de dados do processamento de dados e da parte de comunicação ...

3- Utilizando uma metodologia ágil (ler o manifesto ágil) para gerenciamento de projectos como Extreme Programming (XP) associada a SCRUM … Kanban, Lean

Dito de outra maneira não tenham os olhos muito perto do código se não , não podem ver o resto , de outros aspetos muito importantes como por exemplo a arquitetura e as funcionalidades !


Agora vou explicar como resolver este caso :

1- Arquitetura : Para resolver o caso vou separar o camada apresentação (GUI, IHM) e da parte de comunicação

2- As funcionalidades vistas a través da IHM ou seja a GUI

Numa classe Java nomeada por exemplo  ViewJogoDaForca criar no construtor da classe : JFrame ,  JTextField, JButton, JTextArea
Vamos agora criar um JPanel para o ContentPane da JFrame associado a um BorderLayout
depois criar um JPanel associado a um  FlowLayout no qual vamos meter o JTextField, JButton botão enviar e metemos este JPanel ao norte no JPanel previamente construído.

O JTextArea pode ser metido no "Center" do BorderLayout e o JLabel no South do BorderLayout para desenhar a Forca, com interface será feita através imagens setadas nesse JLabel.

Agora falta apenas usar a técnica para gerências famosos eventos do botão. Técnica das classes internas locais anónimas.
(quando se faz um click no botão faz um apelo a um método que recupera o texto contido no JTextField e envia na rede dos SOCKET …

Quando o servidor responde o JTextArea exibe o texto enviada pelo servidor

Resultado a GUI : consiste em um campo de texto e um botão para o norte e para o sul a área de exibição de texto (JTextArea).

3- Parte de comunicação

Solução :  separar a  exibição do menu e a parte de comunicação
                 -----&gt;  Temos que manter o mesmo código, mas criar métodos diferentes no bom lugar.
                  ----&gt;   O while  devia servir para o menu apresentação num método especial par esse efeito

Experimente estas dicas e se não conseguir sozinho envia massagem para explicar mais como resolver este problema de concepção de programas OO.

Porque aquele que encontra sem buscar há muito tempo busca sem encontrar !

Best regards !

Olá JxtaNode, valeu por responder…
Então, primeiro irei explicar melhor o funcionamento da Classe DatagramClente.java:
Ao executar essa classe, ela cria um Pacote contendo: (mensagem, tamanho dessa msg, ip, porta do servidor), além disso, um identificador exclusivo para cada Cliente.
Exemplo Cliente X. Esse Cliente X ficará no while até acertar a palavra, e nunca irá criar um novo identificador para ele.

Se outra pessoa executar essa Classe, irá criar um novo pacote e um outro identificador Cliente X+1. É dessa forma que o Servidor envia as informações para cada Cliente específico…

Bom, com relação a interface fiz do jeito que vc disse.

  • Crie uma Classe ViewJogo para a Interface:
    • Campo texto;
    • Botão de enviar;
    • Label para setar as imagens da forca e,
    • Text Área para receber as informações.

Interliguei essa classe ViewJogo com a classe do DatagramClient.
ViewJogo envia a letra digitada para DatagramClient. até aqui sem problemas… O porém é:
Toda vez que escrevo um letra no ViewJogo e mando para DatagramClient, essa classe cria um novo Cliente. Dessa forma, não terei controle de cliente e não terei como enviar a
resposta do Servidor para o Cliente certo.

Esse que é o problema do trabalho! Será que consegui ser claro?!
Qualquer coisa posto o código!
Abraço!

J

Bom dia,

O problema vem da falta de visão arquitetónica do programa JAVA do ponte de vista da POO. você deve pensar methods e objetos e não meter tudo no método main()

Na POO cada coisa deve ficar no seu lugar : por exemplo criar uma method java para cada coisa e uma classe para um grupo de methods para cada coisa diferente (Separação de preocupações).

No WHILE você meteu dois aspectos diferentes o aspecto comunicação com sockets e a apresentação do menu e meteu todo no main(). Em fazendo isso criou uma prisão psicológica na qual seu pensamento caio.

O secundo erro foi de meter o WHILE nesse sitio : o while avia de ser metido numa method java separada , na qual você mete o menu (todo o que é System.out.print), que se reexibida a cada vez que o utilizador do programa introduz uma nova letra.

Assim ao meter o while num method java viewMenu() separado : este simples gesto vai liberar sua mente e poder avançar (por que foi esse WHILE danado que o fez bloquear).

Se você aplicar os princípios da POO você vai conseguir :

Algumas regras para resolver o problema :

1- O desenvolvimento pode/deve ser dirigido pela arquitetura e as funcionalidades.

The development should be driven by the architecture and functionalities.

2- Separação de preocupações , “Separation of Concerns (SoC)

Por exemplo separar a apresentação, e estruturas de dados do processamento de dados e da parte de comunicação …

3- Utilizando uma metodologia ágil (ler o manifesto ágil) para gerenciamento de projectos como Extreme Programming (XP) associada a SCRUM … Kanban, Lean

Conclusão para resolver isto :

[…Toda vez que escrevo um letra no ViewJogo e mando para DatagramClient, essa classe cria um novo Cliente…]

Separe a apresentação (IHM = System.out.print() no modo Console e SWING no caso modo GUI) e a comunicação com SOCKETS !!

Tirar o WHILE e meta-o num outro method viewMenu() com o menu .

Criar um outro method (nomeado por exemplo viewMenu() ) para o menu com o WHILE que se reexibida a cada vez que o utilizador do programa introduz uma nova letra.

Outra coisa : Utilize nomes mais explícitos

quebraMsgServidor : quebrar !!! analisar também é dividir por isso é mais elegante de falar em analisar uma massagem proveniente do servidor

Outro exemplo : ViewJogo : Jogos à muitos ! de qual se trata este aqui ?

A minha referencia da POO e COO : Bertrand Meyer criador da linguagem informática Eiffel ( Design by contract (DbC)) ele é Francês trabalha no ETH Zürich : Object-Oriented Software Construction

eu li-o  em francês : Conception et Programmation orientées objet (livro de 1222 paginas)

Cordialmente

Ernest  Duarte
Criado 25 de dezembro de 2012
Ultima resposta 26 de dez. de 2012
Respostas 3
Participantes 2