Java.awt.Robot Problem beim Shift-Druck

Status
Nicht offen für weitere Antworten.

1337iceskater

Aktives Mitglied
Hallo Leute,

ich habe eine ziemlich großes Problem und zwar gehts dabei um den java.awt.Robot.

Ich will mit dem Robot Eingaben simulieren und auch abschicken. Daher will ich vor dem Abschicken die Korrektheit überprüfen. Das hatte ich mit Shift+Linksdrücken vor (erst schreiben, dann markieren, kopieren und aus der Zwischenablage vergleichen). Das Problem ist, dass das Shift nicht zu funktionieren scheint. Wenn ich aber nur einen Großbuchstaben screiben will, funzt es.

So genug Fakten, hier erstmal der Code:

Java:
package robot;

import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.event.KeyEvent;

public class Webrobbi{

	private static Robot r;
	
	public static void use(int i){
		r.keyPress(i);
		r.keyRelease(i);
	}
	
	public static void write(String s){
		for(int i = 0; i < s.length(); i++){
			use(s.charAt(i));
		}
		r.keyPress(  KeyEvent.VK_SHIFT);		//hier funktioniert das Shift
        r.keyPress(  KeyEvent.VK_H);  
        r.keyRelease(KeyEvent.VK_SHIFT);
        r.keyPress(  KeyEvent.VK_H);    
	}
	
	public static String get(){
		Transferable t = null;
		boolean done = false;
		while(!done){
			try{
				t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
				done = true;
			}
			
			catch(Exception e){
				
			}
		}
		try{
			if(t != null && t.isDataFlavorSupported(DataFlavor.stringFlavor)){
				String text = (String)t.getTransferData(DataFlavor.stringFlavor);
				return text;
			}
		}
		catch(Exception e){
			e.printStackTrace();
		}
		return null;
	}
	
	public static boolean checkFor(String s){
		r.keyPress(KeyEvent.VK_SHIFT);		//Dieses Shift wird scheinbar nicht erkannt
		for(int i = 0; i < s.length(); i++){
			r.keyPress(KeyEvent.VK_LEFT);
			r.keyRelease(KeyEvent.VK_LEFT);
		}
		r.keyRelease(KeyEvent.VK_SHIFT);
		r.keyPress(KeyEvent.VK_CONTROL);
		r.keyPress(KeyEvent.VK_C);
		r.keyRelease(KeyEvent.VK_CONTROL);
		r.keyRelease(KeyEvent.VK_C);
		String copy = get();
		if(copy.equalsIgnoreCase(s)){
			return true;
		}
		return false;
	}
	
	public static void main(String[] args) {
		try{
			r = new Robot();
			Runtime.getRuntime().getRuntime().exec("C:\\Windows\\system32\\notepad.exe");
			Thread.sleep(5000);		//warten bis die Anwendung gestartet ist
			String s = "laskdlaksd";
			write(s);
			if(checkFor(s)){
				System.out.println("true");
			}
			else{
				System.out.println("False");
			}
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}
}

Ich hoffe, dass ihr eine Idee habt, warum das nicht funktioniert.
Wenn jemand ne effektivere Idee hat bitte auch posten.
Vielen Dank schonmal :toll:
 
Ja, merkwürdig-undeterministisches Verhalten.... wie auch immer eine Lösung dafür aussehen KÖNNTE, du solltest bedenken, dass die Sache mit den KeyCodes ein bißchen hakelig sein kann - also, man sollte nicht davon ausgehen, dass das (was auch immer man damit macht) wirklich auf ALLEN Betriebssystemen usw. funktioniert... Es gibt da einige diffzil klingene Bugs in der Sun Bugdatabase.... 😱

Wie auch immer: Bei mir tritt dieses Problem nicht auf, wenn "Num Lock" ausgeschaltet ist - dann markiert er den Text, und erkennt ihn auch als richtig. Allerdings sollte NumLock da gar keinen Einfluß darauf haben! Deswegen kann es gut sein, dass das nur irgendein merkwürdiger Zufall ist ... :bahnhof:

Kannst aber mal schauen, wie weit du kommst, wenn du am Anfang mit
Toolkit.getDefaultToolkit().setLockingKeyState(KeyEvent.VK_NUM_LOCK, false);
NumLock ausschaltest. (Programmatisch EINschalten hat bei mir nicht funktioniert - vielleicht ein neuer Bug für die Bugdatabase 😉 )

Damit das ganze überhaupt funktioniert, müßtest du aber in der "use"-Methode als erste Zeile ein
i = Character.toUpperCase(i);
einfügen. Genaugenommen müßtest du jedes einzelne Zeichen, das an die "use"-Methode übergeben wird, überprüfen: Wenn es ein uppercase-character ist, musst du

press shift
press character
release character
release shift

machen, und wenn es ein lowercase character ist, musst du

character = Character.toUpperCase(character);
press character
release character

machen... Von Zahlen, Sonderzeichen & Co mal ganz abgesehen 😉
 
Ja, also der oben geschriebene Code ist auch nichts anderes als n Beispiel Code.

der eigentliche Code sieht anders aus und kann auch mit Sonderzeichen umgehen, ging mir halt nur um das markieren. Und ich hab auch nur vor, das auf Windows laufen zu lassen. Auf meinem Erstellungsrechner funzt das (Laptop), auf nem Testrechner funzt das nicht (Laptop mit angeschlossener Tastatur). Von daher kann das mit dem NumLock wirklich sein. Ich probier das eben mal aus und meld mich dann mit dem Ergebnis zurück 😉 Aber danke auf jeden fall für die schnelle Antwort.

BG
 
JUHU,

es geht :toll:
es lag wirklich am NumLock. Ich lass es jetzt immer kurz vor dem Kopieren ausstellen und danach wieder anstellen. Das funzt klasse, wenn man das Toolkit vorher statisch definiert. Also bei mir siehts funktionierend jetzt so aus:

Java:
package robot;

import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.event.KeyEvent;

public class Webrobbi{

	private static Robot r;
	
	public static void use(int i){
		r.keyPress(i);
		r.keyRelease(i);
	}
	
	public static void switchNumLock(Toolkit tk){
		if(tk.getLockingKeyState(KeyEvent.VK_NUM_LOCK)==true){
			tk.setLockingKeyState(KeyEvent.VK_NUM_LOCK, false);
		}
		else{
			tk.setLockingKeyState(KeyEvent.VK_NUM_LOCK, true);
		}
	}
	
	public static void write(String s){
		for(int i = 0; i < s.length(); i++){
			use(s.charAt(i));
		}
		r.keyPress(  KeyEvent.VK_SHIFT);		//hier funktioniert das Shift
        r.keyPress(  KeyEvent.VK_H);  
        r.keyRelease(KeyEvent.VK_SHIFT);
        r.keyPress(  KeyEvent.VK_H);  
	}
	
	public static String get(){
		Transferable t = null;
		boolean done = false;
		while(!done){
			try{
				t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
				done = true;
			}
			
			catch(Exception e){
				
			}
		}
		try{
			if(t != null && t.isDataFlavorSupported(DataFlavor.stringFlavor)){
				String text = (String)t.getTransferData(DataFlavor.stringFlavor);
				return text;
			}
		}
		catch(Exception e){
			e.printStackTrace();
		}
		return null;
	}
	
	public static boolean checkFor(String s){
		Toolkit tk = Toolkit.getDefaultToolkit();
		switchNumLock(tk);
		r.keyPress(KeyEvent.VK_SHIFT);		//Dieses Shift wird scheinbar nicht erkannt
		for(int i = 0; i < s.length(); i++){
			r.keyPress(KeyEvent.VK_LEFT);
			r.keyRelease(KeyEvent.VK_LEFT);
		}
		r.keyRelease(KeyEvent.VK_SHIFT);
		r.keyPress(KeyEvent.VK_CONTROL);
		r.keyPress(KeyEvent.VK_C);
		r.keyRelease(KeyEvent.VK_CONTROL);
		r.keyRelease(KeyEvent.VK_C);
		String copy = get();
		if(copy.equalsIgnoreCase(s)){
			return true;
		}
		switchNumLock(tk);
		return false;
	}
	
	public static void main(String[] args) {
		try{
			r = new Robot();
			Runtime.getRuntime().getRuntime().exec("C:\\Windows\\system32\\notepad.exe");
			Thread.sleep(5000);		//warten bis die Anwendung gestartet ist
			String s = "laskdlaksd";
			write(s);
			if(checkFor(s)){
				System.out.println("true");
			}
			else{
				System.out.println("False");
			}
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}
}

Auf jeden Fall Vielen Vielen Dank :applaus:
 
Nein, das wird kein Bot für n Spiel. Ich soll von Arbeit aus ne Website automatisch mit Daten füllen. Da ich aber mit Schnittstellen wie HTMLUnit usw. nicht auf die Seite komme (aus welchen Gründen auch immer) mach ich das per Robot. Und damit dann nicht irgendwelche schwachsinnigen Daten auf der Website stehen, wird jeder Eintrag nachträglich auf Korrektheit überprüft.
Ich weiß, das ist nicht die eleganteste Lösung, aber vorerst ist es überhaupt ne Lösung 😉

LG
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben