Ich versuche in einen Textfeld mittels „keyPressed“ die Eingabe des Zeichens ‚@‘ abzufangen.
Leider schlagen sämtliche Versuche fehl
Hier mal ein Teil meiner Versuche, die ich nach längerer Webrecherche ausprobiert habe:
void tfManuelleEingabe_keyPressed( KeyEvent e )
{
if( e.isAltGraphDown() ) // ist seltsamer FALSE, wenn ich die ALT GR-Taste gedrückt halte
{
if( e.getKeyCode() == KeyEvent.VK_Q )
{
e.consume();
}
}
// ------------------------------------------------------------------------------
int onmask = InputEvent.ALT_GRAPH_DOWN_MASK; // hat den Wert 0x2000
if( (e.getModifiersEx() & onmask) == onmask) // das getModifiers liefert nur 0x80 ....
{
e.consume();
}
}
Auch die Prüfung auf das KeyEvent VK_AT klappt nicht …
EDIT:
ICh habe gerade im Debugger gesehen, dass beim Drücken von ALT-GR nacheinander die KeyEvents VK_CONTROL (0x17) und VK_ALT (0x18) kommen …
Ich würde gar nicht so wild versuchen mit Listener das Event abfangen zu wollen, sondern mit einem Document einfach das Einfügen zu verhindern. Funktioniert übrigens auch mit Copy’n’Paste, was bei deiner Variante nicht greifen würde und man so trotzdem ein @ reinkopieren könnte.
Nach einer kurzen Internetsuche mit “java keyevent altgr” hat Hinweise gezeigt, dass altgr auf WindowsSystemen in alt+strg/ctrl übersetzt wird. Das scheint auch vom Tastatur-Layout abhängig zu sein.
Wie das unter Linux oder beim Mac aussieht, kann ich leider nicht sagen.
Wenn ich unter Windows alt+strg+q drücke wird im Editor auch das @ geschrieben, genau wie bei altgr+q. Vielleicht wäre es ein Workaround zugucken ob alt und strg gedrückt worden sind?
Vielleicht wäre es ein Workaround zugucken ob alt und strg gedrückt worden sind
Nicht wirklich, da zwei Events nacheinander kommen, sprich die keyPressed-Methode auch zweimal nacheinander aufgerufen wird … und danach käme ja noch die Taste ‚Q‘
Kann ich also in EINER Prüfung gar zusammen abfragen
Deshalb hatte ich es auch mit „isAltGraphDown()“ versucht, was aber eben FALSE liefert, wenn ich die Taste gedrückt halte …
sondern mit einem Document einfach das Einfügen zu verhindern
EDIT:
das Textfeld ist deklariert als: tfManuelleEingabe.setDocument( new LimitedPlainDocument(40) );
Nur - fange ich denn dabei die Tasten ab ?
noch gar nicht angesprochen ist die keyTyped-Methode, die sich allgemein anbietet,
von der kommt bei der ganzen Sache nur ein Event (! 1), das @ kannst du fertig aus getKeyChar() herausholen (! 2),
dort gibt dann isAltGraphDown() auch true und naheliegend funktionieren ALT_GRAPH_MASK sowie ALT_GRAPH_DOWN_MASK hier jeweils (! 3)
dass bei keyPressed so viele Ereignisse kommen ist mit dem Konzept für die Sondertasten und dann noch dem Konzept AltGraph = Alt + CTRL verständlich,
warum ALT_GRAPH dabei nicht unterstützt wird weiß ich nicht,
nach den Zahlen ist diese Konstante aber ja auch was anderes als Summe Alt + CTRL,
auf die beiden gleichzeitig angefragt würde es auch in keyPressed funktionieren,
nichtmal ALT_CTRL als Alternative ist mit eigener Konstante zur häufigen Verwendung angeboten…,
sieht irgendwie ungut aus, wohl durch diese Tastatur-Übersetzung, nicht in Java eingeplant?
andererseits kann es natürlich auch gewünscht sein, Alt + CTRL von AltGraph zu unterscheiden, was in Windows dann gar nicht geht…
Ok, auf „keyTyped“ hätte vielleicht selbst kommen können, das „getKeyChar“ hatteich bislnag noch nie benutzt!
Hier mal die funktionierende Lösung:
/**
* @brief Die Eingabe der Taste '@' im Textfeld "Manuelle Eingabe" unterdrücken
* @param e = KeyEvent
*/
void tfManuelleEingabe_keyTyped( KeyEvent e )
{
if( e.isAltGraphDown() )
{
if( e.getKeyChar() == '@' )
{
e.consume();
}
}
} // tfManuelleEingabe_keyTyped
Allerdings würde mich jetzt mal grundsätzlich interessieren, warum dann hier das KeyEvent immer 0 ist ??
So ganz logisch findet ich das irgendwie nicht …
Ich wiederhole mich gerne noch mal : Document ! Du verwendest schon ein Document (denn LimetedPlainDocument gibt es nicht in der API), warum schreibst du dann deine insertString() methode nicht so das es entweder das @ stillschweigend rausfiltert oder sogar ne Exception wirft. Sorry, aber einfacher gehts nicht. Ich versteh nicht warum ihr hier immer noch mit irgendwelchen Listenern rumspringt statt direkt ins insert einzugreifen und es dort zu machen. Wie gesgt : Vorteile liegen auf der Hand : funktioniert auch bei Copy’n’Paste, Platformunabhängig da man sich nicht drum kümmern muss wie AltGr nun vom OS gehandhabt wird und scheinbar is ja noch das Problem das einige Methoden garnicht gecallt werden.
Wenn du “e.getKeyChar()” schreibst, kannst du dir “if(e.isAltGraphDown())” sparen, denn ein KeyChar ist nicht von gedrückten Tasten abhängig, sondern vom Tastatur-Layout (evtl. dämlich ausgedrückt, aber ich hoffe du verstehst, dass das @ auf manchen Layouts auch anders, z.B. mit Shift erreicht werden kann).
Darüber hinaus ist die Frage, in welcher Methode du was abfragst. In KEY_PRESSED und KEY_RELEASED Events z.B. sind die KeyCodes relevant und in KEY_TYPED die KeyChars. daraus ergibt sich, dass die Codes evtl. nur in KEY_PRESSED und KEY_RELEASED Events sicher abrufbar sind und die Chars halt in KEY_TYPED.
Ausserdem, wie Sen schon sagte, die Zeichen könnten durch C+P trotzdem in den Text geraten. Demnach wäre ein DocumentFilter die bessere Herangehensweise.
Ich kann sogar ein noch sehr viel greifbareres Beispiel geben :
Ich habe mal für einen Freund ein kleines Tool geschrieben was letzten Endes die Aufgabe hatte Informationen vereinfach darzustellen und nach einem User-Input entsprechende Aktionen durchzuführen. Die Informationen selbst bestanden dabei aus recht simplen Name-Anzahl Paaren. Als User-Input war ein einfach JTextField gegeben.
Ich stand nun vor der Aufgabe mir was einfallen zu lassen wie ich
nur numerischen Input zulasse
prüfe das der Input innerhalb des maximalen Wertes liegt
gegen Manipulation oder Fehleingabe absichere
Vom heutigen Standpunkt aus betrachtet gab sicher einige Dinge die man hätte deutlich eleganter lösen können, damals habe ich mich jedoch, wie ich es auch bei diesem Fall wieder tun würde, für eine Sub-Implementierung von PlainDocument entschieden.
Nach einer kurzen Google-Suche und ein bisschen lesen in der Doc wusste ich dann auch wie es funktioniert und habe entsprechend die insertString()-Methode überschrieben. So konnte ich alle drei Punkte lösen.
nur numerischer Input
War eigentlich recht einfach mit einem if() gelöst (würde ich heute mit nem RegEx machen). Alles was halt nicht 0-9 war wurde ignoriert und aus dem Input entfernt.
Maximalwert prüfen
Dazu war ein kleiner Trick nötig da ich dem Document ja auch noch irgendwie sagen musste was denn überhaupt das Maximum ist. Also einfach einen Konstruktor hinzugefügt der als Parameter einen int hatte und dies als Member gespeichert. In insertString() habe ich dann nach Schritt 1 den bereits vorhandenen Wert (mit getText()) sowie dem Teil der noch hinzugefügt werden sollte einfach in Integer.parseInt() gesteckt und mit einem einfach Op verglichen. Überstieg der neue Wert das Maximum so wurde stattdessen dies eingefügt. Das hatte dann den für mich sehr schönen Effekt das man z.B. auf “9” rumhämmern konnte bis dann auf Grund des Codes automatisch der Höchstwert vorhanden war.
Sicherung gegen Manipulation / Fehlbedienung
Wurd eigentlich durch Punkt 2 erreicht, wäre aber unvollständig gewesen wenn ich es z.B. mit einem Input-Listener versucht hätte denn so wäre ich gegen Copy’n’Paste hilflos gewesen. Also war die Absicherung eben das ich ein Document genutzt habe was direkt vor dem eigentlichen Einfügen geschaltet war. So hatte ich die Kontrolle was auch immer kommen würde das ich erstens nur die für mich nötigen Informationen rausfiltern und diese auch noch auf Gültigkeit prüfen konnte.
Wie erwähnt : hier und da gibt es sicher noch den einen oder anderen Punkt den man noch etwas optimieren könnte, aber die Aufgabe wurde gelöst.
Sicher kann man das auch irgendwie mit Listenern bauen das man halt prüft : ok, was kommt denn überhaupt als Event rein das man hier schon selektiert das halt unerwünschte Events garnicht erst bis zum Input kommen, schlecht allerdings wenn, wie ja hier passiert, das tatsächliche Verhalten vom erwarteten abweicht und sich so Fehler einschleichen. Wie Spacerat schon sagte : es kommt drauf an wann welche Methode mit welchem Event gecallt wird. Es gibt dazu im Sun-TUT ein schönes Listener-Beispiel wo man auch die Codes und Keys bekommt und so zumindest mal gucken kann wie denn so ein “@” für Java wirklich aussieht / zu stande kommt.
ja, gutes Argument
Ich hatte nur kurz den Spielplan gegogglet und wohl leider nicht den Aktuellen erwischt :sick:
Ok, daqnn gewinnen wir eben schon in fünf Wochen … :o)
[QUOTE=mymaksimus]Hach, meine Antwort was doch nicht so ganz nutzlos: Das ganze geht nämlich auch im “keyPressed” event ^^[/QUOTE]Naja, wie mans nimmt. Wie gesagt, haben die KeyChars in KEY_PRESSED und KEY_RELEASED Events genauso wenig Relevanz, wie KeyCodes in KEY_TYPED Events. Das es grösstenteils überall funktioniert ist zwar korrekt, nur sollte man sich darauf aber nicht verlassen.