Laden...

Benutzerdefinierte Tastaturbelegung verwalten (passende Datenstruktur)?

Erstellt von Lotus vor 12 Jahren Letzter Beitrag vor 12 Jahren 1.647 Views
L
Lotus Themenstarter:in
73 Beiträge seit 2011
vor 12 Jahren
Benutzerdefinierte Tastaturbelegung verwalten (passende Datenstruktur)?

Hallo, ich möchte gerne mein Programm auch per Tastatur steuern lassen.
Da das ganze nutzerfreundlich gestaltet werden soll, möchte ich dem Nutzer die Möglichkeit geben, die Belegung nach seinen Wünschen zu gestalten.

Jetzt wollte ich fragen, wie man das Ganze am Besten verwalten könnte? Es soll natürlich keine Belegung doppelt vorkommen, das heißt, wenn ein Buchstabe gewählt wird, der bei einer anderen Belegung schon vorhanden ist, wird die alte Belegung gelöscht. (Hier ist die Frage, wie kann man das umsetzen?)

Zur Zeit hatte ich lediglich eine Klasse mit Attributen:


private Key Action1;
private Key Action2;
....

Allerdings lässt sich hier schlecht vergleichen ob die Buchstaben schon belegt sind.. erst recht, wenn ich später noch Änderungen oder weitere Aktionen hinzufüge.

Meine zweite Idee wäre eine Collection/Array gewesen, aber außer stupides durchgehen aller Actions fällt mir hier auch keine bessere Idee ein...

Was meint ihr?

795 Beiträge seit 2006
vor 12 Jahren
Dictionary<Key, Action>

Gruß, Christian.

`There are 10 types of people in the world: Those, who think they understand the binary system Those who don't even have heard about it And those who understand "Every base is base 10"`
L
Lotus Themenstarter:in
73 Beiträge seit 2011
vor 12 Jahren

Wär es nicht günstiger Key und Action zu tauschen? ALso:


Dictionary<Action, Key> 

Dann könnte ich jedesmal die Action löschen und dann mit dem neuen Key neu setzen...
Andernfalls ein Beispiel:

Wenn ich Key als Key und Action als Value nehme, und ich möchte meiner Aktion "Hüpfe" den Buchstaben H zuweisen. Wie sollte ich dann die alte Belegung von Hüpfe löschen bzw. überschreiben? Oder hab ich nen Denkfehler?

Edit: Ah, ich seh gerade, dass ich damit gar nicht wirklich der Doppelbelegung vorbeugen würde.
Ich würde die alte Action löschen und quasi die mit nem neuen Value neu hinzufügen. Ist denke ich auch machbar 😃

C
2.121 Beiträge seit 2010
vor 12 Jahren

Warum nicht beides? Dann kannst du für jeden Key nachschauen was du tun musst und kannst für jede Action den zugehörigen Key finden und tauschen.

L
Lotus Themenstarter:in
73 Beiträge seit 2011
vor 12 Jahren

Warum nicht beides? Dann kannst du für jeden Key nachschauen was du tun musst und kannst für jede Action den zugehörigen Key finden und tauschen.

Du meinst also, ich soll zwei Dictionaries anlegen? Also quasi immer in beiden alles überschreiben?

5.742 Beiträge seit 2007
vor 12 Jahren

Hallo zusammen,

man sollte sich natürlich noch überlegen, was für Kombinationen man zulassen möchte: Immer nur einzelne Tastenkombinationen oder auch Folgen von Tastenkombinationen wie auch in VS (z.B: STRG + K, STRG + D).

Eine Action würde ich nicht unbedingt verwenden - eher ein ICommand (oder etwas in die Richtung).
Dann kann man dasselbe Command nämlich noch mit einer Beschreibung versehen und gleichzeitig in Menüs anzeigen. Um die Tastenkombination auch dort anzeigen zu können, müsste das Command selbst speichern, über welche Tastenkombination es erreichbar ist (also entweder eine Property vom Typ Key oder vom Typ IEnumerable<Key>). IMHO kann man in der Key Enumertation ja auch Modifiertasten ablegen.

Für's Ermitteln der Tastenkombinationen brauchst du nicht einmal zwangsläufig ein Dictionary: Etwas LINQ tut's auch (pseudomäßig):


var possibleCommand = this.Commands.Where(c => c.ShortcutFits(key)).FirstOrDefault();
if (possibleCommands != null)
   possibleCommand.Execute();

Wenn du Folgen zulässt, wird's natürlich ein bisschen komplexer.

Doppelbelegungen kannst du ähnlich auflösen - es ist sowieso auch hilfreich für den User, wenn er sieht, welche Aktion bisher einer Tastenbelegung zugeordnet ist.

L
Lotus Themenstarter:in
73 Beiträge seit 2011
vor 12 Jahren

Oha, damit haust du mich jetzt ein bisschen aus den Socken. Ich möchte lediglich Einfachbelegungen, also "Q", "A" etc belegen.

Bisher habe ich anstatt der "Action" einfach einen String genommen und diesen dann immer mit switch etc. zugeordnet (find ich ziemlich unschön).

Deinen Code konnte ich leider nicht ganz nachvollziehen... ich nehme an der kommt in eine eigene Klasse welche ich mit ICommand erweitere..

Ich wäre sehr dankbar falls du noch ein bisschen genauer erklären könntest, oder einen weiterführenden Link anzubieten haettest.

5.742 Beiträge seit 2007
vor 12 Jahren

Deinen Code konnte ich leider nicht ganz nachvollziehen... ich nehme an der kommt in eine eigene Klasse welche ich mit ICommand erweitere..

Nur als Denkanstoß hätte ich statt der Action eine Klasse verwendet, die in etwa so aussähe:


public interface ICommand /*evtl. auch anders benannt und von dem FCL-Interface ICommand abgeleitet*/
{
   Key? Shortcut { get; set; } //Der Shortcut-key
   string Description { get; } //Kurze Beschreibung, was diese Aktion macht - z.B., um den User beim Editieren der Keymappings nicht ganz im Regen stehen zu lassen ;-)

   bool ShortcutFits(Key shortcut); //Prüft im einfachsten Fall nur, ob this.Shortcut == shortcut 
   bool CanExecute(); //Damit Buttons entsprechend ausgegraut werden können etc.
   void Execute(); //Führt die Aktion aus
}

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo Lotus,

Du meinst also, ich soll zwei Dictionaries anlegen?

besser wäre es, eine eigene Klasse zu schreiben, die intern von mir aus mit zwei Dictionaries arbeitet und nach außen die Funktionalität für den schnellen Zugriff in beide Richtungen ermöglicht. Wenn du direkt zwei Dictionaries verwendest, besteht immer die Gefahr, dass sie aus dem Takt kommen, also inkonsistent werden. Wenn man die Dictionaries kapselt, muss man sich nur ein dieser einen Stelle um die Konsistenz kümmern.

herbivore

L
Lotus Themenstarter:in
73 Beiträge seit 2011
vor 12 Jahren

Hallo,
das wäre eine gute Idee, aber mir ist gerade noch eine eingefallen und wollte mal fragen was ihr davon haltet:

Ich hab insgesamt nur 7 Buttons. Also eine recht kleine überschaubare Anzahl an Keys die ich zu verwalten habe. Daher hab ich mir überlegt, ich lege 2 Collections (Array/List) an und füge sämtliche Keys hinzu.

Beide Collections sind am Anfang identisch, die eine dient zur Defaultbelegung, die andere zur "aktuellen".
Wenn man einen Key ändern will, geht man die gesamte Liste durch und prüft irgendwo schonmal die Taste vorkommt, wenn ja, dann ändert man diese einfach in dem man sie durch ihre default-Belegung ersetzt, wenn nicht kann man ja einfach den Key direkt ändern.

Ich find das eigentlich recht schlank, ließe sich sogar einfach erweitern.. was meint ihr?

6.911 Beiträge seit 2009
vor 12 Jahren

Hallo Lotus,

das wäre auch möglich, aber wenn du schon

ließe sich sogar einfach erweitern.. was meint ihr?

schreibst bist du doch mit den Dictionaries klar im Vorteil - zumal der indizierte Zugriff auf das Dictionary handlicher ist als wenn jedesmal das Array/Liste durchgeprüft werden muss. Und wenn du das wie herbivore erwähnt hat in eine Klasse packst ist die Verwendung nach außen ganz transparent und einfach.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo Lotus,

dann ändert man diese einfach in dem man sie durch ihre default-Belegung ersetzt

das kann allerdings eine Kettenreaktion verursachen. Sinnvoller wäre die Belegung einfach zu entfernen.

Allerdings ist die Behandlung von Konflikten unabhängig von der Wahl der passenden Datenstruktur.

herbivore