Robot+Swing+Thread para loop infinito

1 resposta
dmandrak

Olá pessoal.
Este é meu primeiro tópico aqui, fiquei muito interessado pois vi que o povo daqui manda bem.
É o seguinte:
Quero criar uma GUI com alguns campos de texto e botões que leia desses campos e passe as strings para um array de ints com o valor ascii para que, ao rodar o robot, ele escreva num determinado local da tela esssas strings alternadamente num loop infinito.
Tive diversos problemas visto que é meu primeiro programa :) mas contornei todos eles inclusive com ajuda daqui. Foram eles: como passar a string pra array de int-ascii, como fazer os botoes funcionarem (actionListener) como fazer o robot escrever e talz.
O robot funciona liso se for pra escrever uma vez só as strings. Quando coloco para loop ele trava a gui (os botões e labels que deveriam mostrar o status não mudam mais quando vai pro sleep) mas escreve com tempo e ordem correta.
O fato é que eu queria manter a gui funcionando pois se eu quero interromper o loop infinito tenho que derrubar o programa no eclipse :( pois os botões estão congelados.
Já fiz minha pesquisa na net e descobri que isso pode ser contornado com Thread, poréééém não tem nenhum lugar assim genial que ajude um java-virgem com linguagem passo-a-passo e exemplo.
De qualquer modo, vou colocar o código aqui.

(Grrrr :? , acabei de ver, não tenho mais a versão que trava a gui mas roda o loop corretamente)
Vou postar a versão com minha tentativa de Thread.

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

public class TesteGUI {

	JButton sleepButton;
	JTextField field1;
	JTextField field2;
	public Boolean sleep=true;
	public Boolean robotRunning=false;
	public Robot rob;
	String tempEmote1="";
	String tempEmote2="";
	int [] emote_1;
	int [] emote_2;
	public int firstRun=0;


	//Getters - Setters Block
		public Boolean getSleep() {
			return sleep;
		}

		public void setSleep(Boolean sleep) {
			this.sleep = sleep;
		}

		public Boolean getRobotRunning() {
			return robotRunning;
		}

		public void setRobotRunning(Boolean robotRunning) {
			this.robotRunning = robotRunning;
		}

		public String getTempEmote1() {
			return tempEmote1;
		}
			
		public void setTempEmote1(String tempEmote1) {
			this.tempEmote1 = tempEmote1;
		}

		public String getTempEmote2() {
			return tempEmote2;
		}

		public void setTempEmote2(String tempEmote2) {
			this.tempEmote2 = tempEmote2;
		}
	// End of Getters - Setters block
	
	/**
	 * @param args
	 * @throws AWTException 
	 */
	
	
	public static void main(String[] args) throws AWTException{
		TesteGUI gui= new TesteGUI();
		gui.go(gui,gui.rob); //creates the GUI and starts the robot
	}

	
	
	public void go(final TesteGUI gui, final Robot rob){
		
		final robotLoop loop=new robotLoop();
		final Thread thread=new Thread(loop);
		JFrame frame= new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		JPanel leftPanel= new JPanel();
		JPanel rightPanel= new JPanel();
	
			
		//Left Panel Component's declarations
		leftPanel.setLayout(new GridLayout(4, 1));
		JLabel lab1 = new JLabel();
		lab1.setText("Dofus BREEDER");
		JLabel statusLabel = new JLabel("Status:  ", JLabel.RIGHT);
				
		field1=new JTextField();
		field1.setText("enter emote1");
		field1.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				 gui.setTempEmote1(field1.getText()); //text field content loaded into a temporary string
			}});
	
		field2=new JTextField();
		field2.setText("");
		field1.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				 gui.setTempEmote2(field2.getText()); //text field content loaded into a temporary string
			}});
		
		//Fill the left panel with its components
		leftPanel.add(lab1);
		leftPanel.add(field1);
		leftPanel.add(field2); 
		leftPanel.add(statusLabel);
		//left panel is complete
				
		
		
		//Right Panel Component's declarations
		rightPanel.setLayout(new GridLayout(4, 1));
		final JLabel lab2 = new JLabel();
		lab2.setText("                            ");
		final JLabel status = new JLabel();
		status.setFont(new Font("Comic Sans", Font.PLAIN, 18));
		status.setOpaque(true);
		status.setBackground(Color.RED);	//status label: shows if the program is sleeping or running
		status.setText(" sleeping ");		//first run, he is sleeping by definition
			
		sleepButton= new JButton("Run");
		sleepButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
							
				gui.setTempEmote1(field1.getText()); //assure that those temporary strings will receive the text field data
				gui.setTempEmote2(field2.getText()); //even if the user do not type 'enter' at the end the text field
				gui.emote_1=gui.converte(tempEmote1);
				gui.emote_2=gui.converte(tempEmote2);//convert the string to array of int - without the '/' in first position
				
				if (gui.getSleep()==true){
					sleepButton.setText("Sleep");
					gui.setSleep(false);
					status.setText(" running ");
					status.setBackground(Color.GREEN); //status label shows running
					if (firstRun==0){ 
						thread.start(); //Starts the ROBOT
						firstRun++;} 
						else{thread.resume();} 
										
					}
					else {
						sleepButton.setText("Run");
						gui.setSleep(true);
						status.setText(" sleeping ");
						status.setBackground(Color.RED); //status label shows sleeping
						thread.suspend();		
					}
						}
		});  //will change the program's state running<->sleeping
          
		
		JButton exitButton= new JButton("exit");
		exitButton.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
		});  //just click the button to exit - (or you can click the top-right 'x' )
		
		//Fill the right panel with its components
		rightPanel.add(exitButton); 
		rightPanel.add(lab2);
		rightPanel.add(sleepButton);
		rightPanel.add(status);
		//right panel is complete
		
				
		//Fill the frame with the two panels and make it visible
		frame.add(BorderLayout.WEST, leftPanel);
		frame.add(BorderLayout.EAST, rightPanel);
		frame.setBounds(400, 400, 200, 150);
		frame.setVisible(true);
		//GUI complete!
				
		}



	
	
	public int[] converte(String emoteToConvert){ //takes a String and returns an int array with char-by-char ASCII code
		int[] emoteToReturn=new int[emoteToConvert.length()];
		String upperEmoteToConvert=emoteToConvert.toUpperCase();
		for(int i=0; i < emoteToConvert.length()-1;i++){
			emoteToReturn[i]=(int) upperEmoteToConvert.charAt(i+1); //int i = (int) s -> i receives the ascii code of string s
		}			
		return emoteToReturn;
	}
		
	
	
	class robotLoop implements Runnable{

		@Override
		public void run() {
			// TODO Auto-generated method stub
			//robot with infinite loop
				
				try {
					Thread.sleep(5000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}//takes 5s to start
				
				//Starts the infinite loop
				while(sleep==false){	
					for (int i = 0; i < emote_1.length; i++) {
						     if (i==0){
						    	rob.keyPress(KeyEvent.VK_DIVIDE);//first emote character must be '/' 
						     	}
						     else{
						     rob.keyPress(emote_1[i-1]);
						     }
						     rob.delay(1000);
						 }
						 try {
							Thread.sleep(4000); // 8-9 seconds total time
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						 rob.keyPress(KeyEvent.VK_ENTER);
						 //First emote done
						 
						 //8-9 seconds to write and enter the oher, 4-5 to write + 4 to enter
						 for (int i = 0; i < emote_2.length; i++) {
						     if (i==0){
						    	rob.keyPress(KeyEvent.VK_DIVIDE);//first emote character must be '/' 
						     	}
						     else{
						     rob.keyPress(emote_2[i-1]);
						     }
						     rob.delay(1000);
						 }
						 try {
								Thread.sleep(4000); // 8-9 seconds total time
							} catch (InterruptedException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						 rob.keyPress(KeyEvent.VK_ENTER);
					}
			}

		 
				
			}
			
		}

Rodando hoje, como está, me responde:
[color=red]Exception in thread "Thread-0" java.lang.NullPointerException
at RobotDemo.TesteGUI$robotLoop.run(TesteGUI.java:434)
at java.lang.Thread.run(Unknown Source)[/color]
434 é a linha: rob.keyPress(KeyEvent.VK_DIVIDE);//first emote character must be '/'

Já adianto que eu fui modificando diversos lugares do programa pra tentar resolver e com isso, provavelmente, ficaram alguns lixos pra traz. Desculpem-me por isso, tentarei não fazer mais porque também me atrapalha bastante...

(pelo menos os comentários, imagino eu, estão bem feitos)

Agradeço ae pela ajuda.

Abraços

ps1: aconselho vocês, caso rodem o meu programa, deixar o 'focus' em algum campo de texto, como num notepad ou coisa do tipo, pq pra ver se funciona é legal você deixar o robot escrever em algum lugar.
ps2:Acho válido dizer que não estou tendo problemas com string, arrays e etc. meu problema é como fazer o thread parar o programa quando o sleep=true (ou quando o botão de sleep for acionado, o que dá no mesmo).
No momento, não sei porque, o robot não está nem mesmo escrevendo. Está dando nullpointerexception...

1 Resposta

dmandrak

e ae pessoal?
ninguém pra me ajudar?

Nessa versão aqui ele roda o loop infinito na moral, sem dar nenhum erro, MAS segura a gui, nao dexando dar exit (tem que derrubar no eclipse)

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.Robot;

public class TesteGUI {

	JButton sleepButton;
	JTextField field1;
	JTextField field2;
	public Boolean sleep=true;
	public Boolean robotRunning=false;

	String tempEmote1="";
	String tempEmote2="";
	int [] emote_1;
	int [] emote_2;
	public int firstRun=0;


	//Getters - Setters Block
		public Boolean getSleep() {
			return sleep;
		}

		public void setSleep(Boolean sleep) {
			this.sleep = sleep;
		}

		public Boolean getRobotRunning() {
			return robotRunning;
		}

		public void setRobotRunning(Boolean robotRunning) {
			this.robotRunning = robotRunning;
		}

		public String getTempEmote1() {
			return tempEmote1;
		}
			
		public void setTempEmote1(String tempEmote1) {
			this.tempEmote1 = tempEmote1;
		}

		public String getTempEmote2() {
			return tempEmote2;
		}

		public void setTempEmote2(String tempEmote2) {
			this.tempEmote2 = tempEmote2;
		}
	// End of Getters - Setters block
	
	/**
	 * @param args
	 * @throws AWTException 
	 * @throws AWTException 
	 */
	
	
	public static void main(String[] args) throws AWTException {
		Robot rob = new Robot(); 
		TesteGUI gui= new TesteGUI();
		gui.go(gui,rob); //creates the GUI and starts the robot
	}

	
	
	public void go(final TesteGUI gui, final Robot rob){
		
		
		JFrame frame= new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		JPanel leftPanel= new JPanel();
		JPanel rightPanel= new JPanel();
	
			
		//Left Panel Component's declarations
		leftPanel.setLayout(new GridLayout(4, 1));
		JLabel lab1 = new JLabel();
		lab1.setText("Dofus BREEDER");
		JLabel statusLabel = new JLabel("Status:  ", JLabel.RIGHT);
				
		field1=new JTextField();
		field1.setText("enter emote1");
		field1.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				 gui.setTempEmote1(field1.getText()); //text field content loaded into a temporary string
			}});
	
		field2=new JTextField();
		field2.setText("");
		field1.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				 gui.setTempEmote2(field2.getText()); //text field content loaded into a temporary string
			}});
		
		//Fill the left panel with its components
		leftPanel.add(lab1);
		leftPanel.add(field1);
		leftPanel.add(field2); 
		leftPanel.add(statusLabel);
		//left panel is complete
				
		
		
		//Right Panel Component's declarations
		rightPanel.setLayout(new GridLayout(4, 1));
		final JLabel lab2 = new JLabel();
		lab2.setText("                            ");
		final JLabel status = new JLabel();
		status.setFont(new Font("Comic Sans", Font.PLAIN, 18));
		status.setOpaque(true);
		status.setBackground(Color.RED);	//status label: shows if the program is sleeping or running
		status.setText(" sleeping ");		//first run, he is sleeping by definition
			
		sleepButton= new JButton("Run");
		sleepButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
							
				gui.setTempEmote1(field1.getText()); //assure that those temporary strings will receive the text field data
				gui.setTempEmote2(field2.getText()); //even if the user do not type 'enter' at the end the text field
				gui.emote_1=gui.converte(tempEmote1);
				gui.emote_2=gui.converte(tempEmote2);//convert the string to array of int - without the '/' in first position
				
				if (gui.getSleep()==true){
					sleepButton.setText("Sleep");
					gui.setSleep(false);
					status.setText(" running ");
					status.setBackground(Color.GREEN); //status label shows running
					gui.startRobot(gui, rob);
					
					}
					else {
						sleepButton.setText("Run");
						gui.setSleep(true);
						status.setText(" sleeping ");
						status.setBackground(Color.RED); //status label shows sleeping
						//thread.suspend();		
					}
						}
		});  //will change the program's state running<->sleeping
          
		
		JButton exitButton= new JButton("exit");
		exitButton.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
		});  //just click the button to exit - (or you can click the top-right 'x' )
		
		//Fill the right panel with its components
		rightPanel.add(exitButton); 
		rightPanel.add(lab2);
		rightPanel.add(sleepButton);
		rightPanel.add(status);
		//right panel is complete
		
				
		//Fill the frame with the two panels and make it visible
		frame.add(BorderLayout.WEST, leftPanel);
		frame.add(BorderLayout.EAST, rightPanel);
		frame.setBounds(400, 400, 200, 150);
		frame.setVisible(true);
		//GUI complete!
				
		}



	
	
	public int[] converte(String emoteToConvert){ //takes a String and returns an int array with char-by-char ASCII code
		int[] emoteToReturn=new int[emoteToConvert.length()];
		String upperEmoteToConvert=emoteToConvert.toUpperCase();
		for(int i=0; i < emoteToConvert.length()-1;i++){
			emoteToReturn[i]=(int) upperEmoteToConvert.charAt(i+1); //int i = (int) s -> i receives the ascii code of string s
		}			
		return emoteToReturn;
	}
		
		
				
	public void startRobot(TesteGUI gui, Robot rob){

		while(gui.getSleep()==false){	
			for (int i = 0; i < gui.emote_1.length; i++) {
				     if (i==0){
				    	rob.keyPress(KeyEvent.VK_DIVIDE);//first emote character must be '/' 
				     	}
				     else{
				     rob.keyPress(gui.emote_1[i-1]);
				     }
				     rob.delay(1000);
				 }
				 
					rob.delay(4000); // 8-9 seconds total time
				
				 rob.keyPress(KeyEvent.VK_ENTER);
				 //First emote done
				 
				 //8-9 seconds to write and enter the oher, 4-5 to write + 4 to enter
				 for (int i = 0; i < gui.emote_2.length; i++) {
				     if (i==0){
				    	rob.keyPress(KeyEvent.VK_DIVIDE);//first emote character must be '/' 
				     	}
				     else{
				     rob.keyPress(emote_2[i-1]);
				     }
				     rob.delay(1000);
				 }
				 
				 rob.delay(4000); // 8-9 seconds total time
				 
				 rob.keyPress(KeyEvent.VK_ENTER);
			}
	}//end of startRobot

		
	}//end of class TesteGUI

EDIT FINAL:
enfim, resolvi ;)
foi com thread mesmo.
caso interesse a alguem entre em contato comigo.
senao, nao vou floodar o forum com codigo inutil hehehehhe

abraços

Criado 29 de maio de 2008
Ultima resposta 3 de jun. de 2008
Respostas 1
Participantes 1