# Tastatureingaben abfangen



## Kaladial (7. Dez 2009)

moin

ich hätte mal wieder nen problem:
ich hab nen kleines programm das folgendes machen soll: 
mit meinem handscanner der über usb angeschlossen ist und der seinen gelesenen string einfach als tastatureingabe ausgibt 
will ich ein feld mit dem inhalt des gelesenen strings füllen ... 

so zur erklärung: 
ich hab nen handscanner 
wenn ich dort auf lesen drücke gibt der den barcode der er gelesen hat auf der tastatur aus.
dieses event will ich abfangen und in ein textfeld rein schreiben.

wie kann ich das machen ? 
ich habs mit keylistener versucht aber irgendwie geht das net ... 
also ich hab nen startknopf der den focus auf dieses textfeld setzt (setFocusable ist doch die richtige funktion dafür oder?)
und auf dem textfeld liegt wie gesagt der keylistener ... nur passiert da irgendwie gar nix... 

wieso ??? 
thx für hilfe 
Kala


----------



## Kaladial (7. Dez 2009)

ok problem gefunden ... ich darf das feld wo der listner liegt natürlich net enable false machen ...


----------



## KrokoDiehl (7. Dez 2009)

... wir helfen gern 
Vielleicht bringt dir das auch was: Global Key Listener Example.


----------



## Kaladial (7. Dez 2009)

...


----------



## Kaladial (7. Dez 2009)

ahja ich hab diesen globalen keylistner mal ausprobiert ... 

2 fragen hab ich dazu: 
wenn ich sage: hotkeyManager = GlobalHotkeyManager.getInstance();
wie kann ich dann auf die buchstaben was auch immer zugreifen ?
also wo seh ich was als eingabe kam ??? 

2.) wie kann ich den listner wieder deaktivieren ???


----------



## KrokoDiehl (7. Dez 2009)

Alles was diese Implementierung tut, steht in der 
	
	
	
	





```
dispathEvent()
```
-Methode. D.h. hier kannst du nach _KeyEvent _abfragen und dann das gleiche tun, wie z.B. in einem _KeyListener_. Wichtig ist nur, dass du alles andere an die Supermethode weiterleitest.
Wenn du ihn nicht haben willst, dann muss der Code aus dem _static_-Block weg, bzw. irgendwo ein Flag einbauen, dass die 
	
	
	
	





```
dispathEvent()
```
 alles direkt an die Supermethode weiterleitet und sonst nichts macht.


----------



## Kaladial (7. Dez 2009)

sorry aber : WAT ??? 

also folgendes: ich hab die class : GlobalHotkeyManager.java so übernommen wie sie in dem beispiel beschrieben ist... 
zusaätzlich hab ich in meiner main-java-datei 	"public GlobalHotkeyManager hotkeyManager = null;" deklariert.

und in meinem jframe hab ich 2 jbutton und 1 textfeld... 
wenn ich nun den 1. button drücke wird "hotkeyManager = GlobalHotkeyManager.getInstance();" ausgeführt... wenn ich nun in dem beispiel den debugmodus einschalte wird mir auf der komandozeile genau das ausgegeben was ich an tasten drück... 

dieses möchte ich nun aber an meine main-datei übergeben und in dem textfeld ausgeben ...
und der 2. button soll dazu da sein den listner zu deaktivieren ... 

ich baue eben mal nen kleines beispielprogramm um das zu verdeutlichen ... dauert aber noch 2 min


----------



## Kaladial (7. Dez 2009)

TestScanner.java:

```
package Handscanner;

import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.Rectangle;
import javax.swing.JTextField;

public class TestScanner extends JFrame {

	private static final long serialVersionUID = 1L;
	private JPanel jContentPane = null;
	private JButton jButtonAN = null;
	private JButton jButtonAus = null;
	private JTextField jTextFieldAusgabe = null;
	public GlobalHotkeyManager hotkeyManager = null;
	/**
	 * This is the default constructor
	 */
	public TestScanner() {
		super();
		initialize();
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setSize(300, 200);
		this.setContentPane(getJContentPane());
		this.setTitle("JFrame");
	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(null);
			jContentPane.add(getJButtonAN(), null);
			jContentPane.add(getJButtonAus(), null);
			jContentPane.add(getJTextFieldAusgabe(), null);
		}
		return jContentPane;
	}

	/**
	 * This method initializes jButtonAN	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJButtonAN() {
		if (jButtonAN == null) {
			jButtonAN = new JButton();
			jButtonAN.setBounds(new Rectangle(18, 11, 69, 37));
			jButtonAN.setText("AN");
			jButtonAN.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					hotkeyManager = GlobalHotkeyManager.getInstance();
				}
			});
		}
		return jButtonAN;
	}

	/**
	 * This method initializes jButtonAus	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJButtonAus() {
		if (jButtonAus == null) {
			jButtonAus = new JButton();
			jButtonAus.setBounds(new Rectangle(18, 58, 66, 40));
			jButtonAus.setText("Aus");
			jButtonAus.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					System.out.println("actionPerformed()"); // TODO Auto-generated Event stub actionPerformed()
				}
			});
		}
		return jButtonAus;
	}

	/**
	 * This method initializes jTextFieldAusgabe	
	 * 	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getJTextFieldAusgabe() {
		if (jTextFieldAusgabe == null) {
			jTextFieldAusgabe = new JTextField();
			jTextFieldAusgabe.setBounds(new Rectangle(139, 48, 139, 26));
		}
		return jTextFieldAusgabe;
	}

}
```

GlobalHotkeyManager.java

```
package Handscanner;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class GlobalHotkeyManager extends EventQueue {
	private static final boolean DEBUG = true; // BUG? what's that? ;-))
	private static final GlobalHotkeyManager instance = new GlobalHotkeyManager();
	private final InputMap keyStrokes = new InputMap();
	private final ActionMap actions = new ActionMap();
	static {
    // here we register ourselves as a new link in the chain of
    // responsibility
		Toolkit.getDefaultToolkit().getSystemEventQueue().push(instance);
	}
	private GlobalHotkeyManager() {} // One is enough - singleton
	public static GlobalHotkeyManager getInstance() {
		return instance;
	}
	public InputMap getInputMap() {
		return keyStrokes;
	}
	public ActionMap getActionMap() {
		return actions;
	}
	protected void dispatchEvent(AWTEvent event) {
		if (event instanceof KeyEvent) {
			// KeyStroke.getKeyStrokeForEvent converts an ordinary KeyEvent
			// to a keystroke, as stored in the InputMap.  Keep in mind that
			// Numpad keystrokes are different to ordinary keys, i.e. if you
			// are listening to
			KeyStroke ks = KeyStroke.getKeyStrokeForEvent((KeyEvent)event);
			if (DEBUG) System.out.println("KeyStroke=" + ks);
				String actionKey = (String)keyStrokes.get(ks);
			if (actionKey != null) {
				if (DEBUG) System.out.println("ActionKey=" + actionKey);
					Action action = actions.get(actionKey);
				if (action != null && action.isEnabled()) {
					// I'm not sure about the parameters
					action.actionPerformed(new ActionEvent(event.getSource(), event.getID(), actionKey, ((KeyEvent)event).getModifiers()));
					return; // consume event
				}
			}
		}
		super.dispatchEvent(event); // let the next in chain handle event
	}
}
```


----------



## KrokoDiehl (7. Dez 2009)

Das Problem ist folgender Teil im HKM (HotKeyManager):

```
static {
    // here we register ourselves as a new link in the chain of
    // responsibility
        Toolkit.getDefaultToolkit().getSystemEventQueue().push(instance);
    }
```
Der sorgt dafür, dass er immer geladen wird, egal ob du
	
	
	
	





```
getInstance()
```
 aufrufst, oder nicht. Zwei Lösungsansätze: 
1. Das "static" wegmachen.
2. Den HKM á la lazy-creation umbauen, d.h. den obigen Code in den HKM-Konstruktor setzen und in 
	
	
	
	





```
getInstance()
```
 folgendes schreiben:

```
if (instance == null)
    instance = new GlobalHotkeyManager();
return instance;
```
(--> Singleton)

Grundsätzlich funktioniert der HKM wie ein _KeyListener_:

```
protected void dispatchEvent(AWTEvent event) {
        if (event instanceof KeyEvent) {
            // code vom KeyListener...
        }
        
        // normales Event-Handling
        super.dispatchEvent(event); 
}
```
D.h. an der o.g. muss du an dein Textfeld kommen und die Eingaben reinsetzen...


----------



## Kaladial (7. Dez 2009)

kannst du mir das in meinen code einbauen ??? 
weil irgendwie bekomm ich das net hin ...


```
public class Singleton {
  private static Singleton instance;
  
  private Singleton() {
  }
        
  public static synchronized Singleton getInstance() {
    if (instance == null) {
        instance = new Singleton();
    }
    return instance;
  }
}
```

^^ auf die art und weise hab ich das umgebaut ... nu geht nix mehr


----------



## KrokoDiehl (7. Dez 2009)

```
public class GlobalKeyListener extends EventQueue
{
    private static GlobalKeyListenern instance = null;
    
    public static GlobalKeyListener getInstance()
    {
        if (instance == null)
            instance = new GlobalKeyListener();
        return instance;
    }

    private GlobalKeyListener()
    {
        Toolkit.getDefaultToolkit().getSystemEventQueue().push(this);
    }

    public void dispatchEvent(AWTEvent event)
    {   
        if (event instanceof KeyEvent)
        {
            KeyEvent kEvent = (KeyEvent)event;
            //hier was tun...
        }             

        super.dispatchEvent(event);
    }
}
```

Hier, das wäre der _GlobalKeyManager _als Singleton. Wobei es nicht nötig wäre... aber egal, will dich nicht weiter verwirren


----------



## Kaladial (8. Dez 2009)

ok so das wäre jetzt die möglichkeit das es wieder funktioniert ... 
jetzt sind noch 2 sachen offen:

1.) wie deaktiviere ich das nun wieder? 
bin mir nicht sicher aber einfach den aufruf: 

```
hotkeyManager = GlobalHotkeyManager.getInstance();
```
wieder auf null setzten hat nix gebracht ... 

2.) wie schreib ich nun aus dem event raus in mein textfeld?
weil dierekt auf das textfeld zugreifen hat net geklappt auch nachdem ich es public gemacht hab ...


----------



## KrokoDiehl (8. Dez 2009)

Zuerst einmal:
Sobald ein _GlobalKeyListener _erstellt wird, setzt er sich in die _SystemEventQueue _(vgl. Konstruktor). Habe spontan keine Methode gefunden, die ihn da wieder rausholt. Aber wenn du ihn nicht drin haben willst, dann brauchst du auch kein 
	
	
	
	





```
getInstance()
```
 aufrufen...

Dann:
Wenn du von Klasse A auf Klasse B (A= GlobalKeyListener, B= Textfeld) zugreifen willst, gibt es ca. 100 Möglichkeiten. Die wohl einfachste ist, dass du A eine Referenz von B gibst, á la

```
public class A
{
    protected B meinB = null;

    public void setB(B neuesB)
    {
        meinB = neuesB;
    }
}
```
So könntest du dem GKeyListener eine Referenz vom Textfeld übergeben, in das er dann die _KeyEvent _reinschreibt.
Aber wie oben schon gesagt: Du erwähntest, dass dein Programm auch ohne geht, warum also die Mühe...


----------



## Ebenius (8. Dez 2009)

KrokoDiehl hat gesagt.:


> Habe spontan keine Methode gefunden, die ihn da wieder rausholt.


Die Methode pop() (protected) holt ihn überraschend da wieder raus. ;-)

Ebenius


----------



## Kaladial (8. Dez 2009)

die variante mit dem globalen listner gefällt mir besser, da ich mit meiner anderen variante probleme mit sonderzeichen hab... 

also ich hab ja einen barcodescanner der dmax codes liest ..
der dmax code wird aus bestimmten komponenten zusammen gesetzt unter andern mit einer seriennummer die zum abschluss das zeichen /f oder ascii 29 enthält ... meine bisherige variante hat damit n bissi probleme die der globallistner nicht hatte ... daher wollte ich gern diesen benutzen ... 

und hmmm das man den nicht deaktivieren kann ist n bissi doof ... 
hat da vielleicht wer anders noch ne idee?


----------



## Ebenius (8. Dez 2009)

Ebenius hat gesagt.:


> Die Methode pop() (protected) holt ihn überraschend da wieder raus. ;-)


Ich zitiere mich auch gern selbst, kein Problem. :-D

Ebenius


----------



## Kaladial (8. Dez 2009)

Ebenius hat gesagt.:


> Die Methode pop() (protected) holt ihn überraschend da wieder raus. ;-)
> 
> Ebenius



hotkeyManager.pop();

^^ das gibt es net ... wie meinst du das `???


----------



## Kaladial (8. Dez 2009)

ah habs hinbekommen ... instance.pop() ^^ thx


----------



## KrokoDiehl (8. Dez 2009)

Ach muh, die ist _protected_, daher hab ich die nicht gefunden...


----------



## Kaladial (8. Dez 2009)

KrokoDiehl hat gesagt.:


> Zuerst einmal:
> Sobald ein _GlobalKeyListener _erstellt wird, setzt er sich in die _SystemEventQueue _(vgl. Konstruktor). Habe spontan keine Methode gefunden, die ihn da wieder rausholt. Aber wenn du ihn nicht drin haben willst, dann brauchst du auch kein
> 
> 
> ...




hmmm das versteh ich noch nicht so ganz ... 
ich hab in meinem testprogramm:
TestScanner ein textfeld das jTextFieldAusgabe heist... 

laut deiner beschreibung müsste mein code so ausehn:


```
public class GlobalHotkeyManager
{
    protected jTextFieldAusgabe meinB = null;

    public void setB(jTextFieldAusgabe neuesB)
    {
        meinB = neuesB;
    }
}
```

^^ und das geht net ... 
ich will ja auch eigentlich nur auf settext von jTextFieldAusgabe zugreifen ...


----------



## KrokoDiehl (8. Dez 2009)

Dein Textfeld ist eher vom Typ _JTextField_...


----------



## Kaladial (8. Dez 2009)

jo das mein ich ja ... wie bekomm ich aber die referenz auf mein JTextField??

also ich hätte sowas erwartet:

JTextField meinTF = jTextFieldAusgabe;

oder 

JTextField meinTF = TestScanner.jTextFieldAusgabe;

um dann in der dispatchEvent - Funktion mit meinTF.setText();
den inhalt zu füllen... aber das geht nicht ... ich bekomm mit TestScanner.   -> keine anzeige von jTextFieldAusgabe
und wenn ich sag: TestScanner.this.jTextFieldAusgabe bekomm ich fehlermeldungen ...


----------



## KrokoDiehl (8. Dez 2009)

```
public class GlobalKeyListener extends EventQueue
{
    private static GlobalKeyListenern instance = null;
    
    public static GlobalKeyListener getInstance()
    {
        if (instance == null)
            instance = new GlobalKeyListener();
        return instance;
    }


    protected JTextField inputField = null;
    protected boolean disabled = false;

    private GlobalKeyListener()
    {
        Toolkit.getDefaultToolkit().getSystemEventQueue().push(this);
    }
 
    public void setTextfield(JTextField field)
    {
        inputField = field;
    }
    
    public void disable()
    {
        disabled = true;
    }

    public void enable()
    {
        disabled = false;
    }

    public void removeListener()
    {
        // s. Ebenius' Post
        this.pop();
    }

    @Override
    public void dispatchEvent(AWTEvent event)
    {   
        if (event instanceof KeyEvent && ! disabled)
        {
            KeyEvent kEvent = (KeyEvent)event;
            if (inputField != null)
                inputField.setText( inputField.getText() + kEvent.getKeyChar() );
        }             
 
        super.dispatchEvent(event);
    }
}
```

Dann kannst du ihn von außen wie folgt behandeln:

```
GlobalKeyListener gkl = GlobalKeyListener.getInstance();
gkl.setTextfield(jTextFieldAusgabe);
```
...und alles sollte tun, ohne es getestet zu haben


----------



## Kaladial (8. Dez 2009)

ich danke euch  so funktioniert es !!


----------



## KrokoDiehl (8. Dez 2009)

Heureka


----------



## Ebenius (8. Dez 2009)

Erledigt? http://www.java-forum.org/forum-faq-beitraege/86306-thema-erledigt-markieren.html

Ebenius


----------

