C #: erhalten, die Taste wurde in einer Reihe von gtk # -Knöpfe gedrückt?
Frage
Ich habe eine Reihe von Tasten, die alle das gleiche Verfahren, jedoch mit dem Index der Schaltfläche als Argument nennen werden.
using System;
using Gtk;
public class Input : Gtk.Window {
private Gtk.Button[] plus;
public Input() : base(Gtk.WindowType.Toplevel) {
plus = new Button[10];
[...]
for (uint i = 0; i < 10; i++) {
plus[i] = new Button();
plus[i].Name = i.ToString();
plus[i].ButtonPressEvent += AddButtonPressed;
}
}
Ich habe versucht, es mit dieser Methode, aber es scheint es nicht einmal, da es aufgerufen wird, erfolgt keine Ausgabe:
protected virtual void AddButtonPressed(object sender, System.EventArgs e) {
Console.WriteLine("Button pressed");
for (uint i = 0; i < plus.Length; i++) {
if (sender.Equals(plus[i])) {
uint index = i;
i = (uint)plus.Length;
Console.WriteLine(index);
}
}
Vielleicht kann mir jemand in die richtige Richtung? Danke.
Lösung
Kurze Antwort:
[GLib.ConnectBefore]
protected virtual void AddButtonPressed(object sender, EventArgs e) {
Console.WriteLine("Button pressed");
for (uint i = 0; i < plus.Length; i++) {
if (sender.Equals(plus[i])) {
uint index = i;
i = (uint)plus.Length;
Console.WriteLine(index);
}
}
}
Rambling Erklärung:
Dies ist tatsächlich eine interessante Frage. Es dauerte ein wenig zu finden suchen, aber GTK # 's FAQ ( aber ich denke nicht häufig verbunden mit) sagt:
"Ab Release 0.15, begann Gtk # unter Verwendung des Flags, wenn CONNECT_AFTER Ereignishandler Signale. Dies bedeutet, dass die Event-Handler sind erst nach dem Standardsignal laufen Handler, das bedeutet, dass das Widget wird aktualisiert, wenn das Ereignis Handler laufen. Ein Nebeneffekt davon Änderung ist, dass in dem Fall, in dem Standard-Handler return true zu stoppen Signal propogation, Ereignisse Gtk # wird nicht emittiert werden. Dies ist der Fall für Beispiel in Gtk.Button, wo die Tastendruck-Ereignis Standardsignal Handler außer Kraft gesetzt Gepresste auszusenden Veranstaltungen.
Während potenziell verwirrend, ist dies nicht wirklich ein Problem. Wenn Sie eine Gtk.Button, Sie bekommen ein Widget dass emittiert Pressed Ereignisse in Reaktion BUTTON1 drückt. Wenn Sie auch wollen Ihre Button Farben zu ändern, oder Popup ein Kontextmenü auf Button3 Pressen, das ist kein Gtk.Button. Die richtige Weg, ein solches Widget zu implementieren ist, Unterklasse Gtk.Button und überschreiben die OnButtonPressEvent virtuelle Methode zu implementieren Sie die neuen Verhaltensweisen Wunsch. "
Wenn es nicht für waren „öffentlichen Aufschrei“ (selten ein Zeichen für eine gute Schnittstelle), gäbe es keine Möglichkeit, dies zu vermeiden, es sei denn, die Unterklassen in C # manchmal ärgerlich ist aufgrund des Fehlens von anonymen Klassen. Aber zum Glück, du bist nicht die erste Person, um dieses Problem zu haben. Also das ist, wo das GLib.ConnectBefore Attribut kommt in. Es im Grunde sagt, rufen Sie diese Event-Handler zuerst so dass die Veranstaltung nicht von Gtk + verschlungen wird.
Der Ärger endet nicht dort aber. Ich ursprünglich wollte vorschlagen, eine gute bewährte Lösung der Anwendung „extra“ Parameter Event-Handler übergeben. In diesem Fall würde dies ermöglichen es Ihnen, den Index zu finden, ohne Gleichen oder die Name
Zeichenfolge verwendet Es handelt sich im Grunde ein Wrapper-Delegierten zu schaffen, dass „gibt vor,“ ein ButtonPressEventHandler zu sein, aber intern übergibt ein int Ihre Begleitband Methode:
Func<uint, ButtonPressEventHandler> indexWrapper = ((index) => ((s, e) => { AddButtonPressed_wrapped(s, e, index); }));
...
plus[i].ButtonPressEvent += indexWrapper(i);
...
protected virtual void AddButtonPressed_wrapped(object sender, EventArgs e, uint index)
{
Console.WriteLine("Button pressed");
Console.WriteLine("Index = {0}", index);
}
Es kompiliert und läuft ohne Fehler, aber es hat das gleiche Problem, das Ereignis nie ausgelöst. Ich erkennen, dass Sie nicht ein Attribut direkt auf einem Delegaten / Lambda setzen. Also auch wenn der Träger Methode der Delegierte hat [GLib.ConnectBefore]
nicht der Fall, so ist es nicht.
Als abschließende Bemerkung, könnten Sie das Klickereignis wie in dieses API Beispiel . Ich überprüfte, dass es wie erwartet funktioniert. Man würde denken, dass es nur auf Mausklicks feuern würde, aber es funktioniert tatsächlich Feuer auf Leer auch.
Andere Tipps
for (uint i = 0; i < 10; i++)
{
plus[i] = new Button();
plus[i].Data.Add("Index",i);
plus[i].ButtonPressEvent += AddButtonPressed;
Add(plus[i]);
}
Handler:
protected virtual void AddButtonPressed(object sender, System.EventArgs e) {
Console.WriteLine("Button pressed");
Gtk.Button button = sender as Gtk.Button;
Console.WriteLine("Index: {0}", button.Data["Index"]);
}
Ich bin ziemlich sicher, dass Sie tatsächlich benötigen, um die Tasten, um die GTK Fenster Hierarchie hinzufügen, so etwas wie:
for (uint i = 0; i < 10; i++) {
plus[i] = new Button();
plus[i].Name = i.ToString();
plus[i].ButtonPressEvent += AddButtonPressed;
Add(plus[i]);
}
Sollte die ähnlich sein, nie wirklich GTK verwendet <. <
Verwenden Tag-Eigenschaft, wenn Gtk-Taste hat eine.
for (uint i = 0; i < 10; i++) {
plus[i] = new Button();
plus[i].Name = i.ToString();
plus[i].ButtonPressEvent += AddButtonPressed;
plus[i].Tag = i;
Add(plus[i]);
}
Handler:
protected virtual void AddButtonPressed(object sender, System.EventArgs e) {
Console.WriteLine("Button pressed");
Gtk.Button button = sender as Gtk.Button;
Console.WriteLine("Index: {0}", button.Tag);
}