2009-05-25 10 views
1

私は、すべて同じメソッドを呼び出しますが、ボタンのインデックスを引数として持つボタンの配列を持っています。C#:gtk# - ボタンの配列でどのボタンが押されたかを取得しますか?

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; 
     } 
    } 

私は、このメソッドを使用して、それを試してみましたが、出力がないとして、それがさえ呼ばれないますようだ:

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); 
     } 
    } 

たぶん誰かがすることができます正しい方向に私を向ける?おかげさまで

答えて

2

クイック答え:

[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); 
     } 
    } 
} 

ランブリング説明:

これは実際に興味深い質問です。これは、リリース0.15のとおり、のGtk#は が信号にイベントハンドラを接続する際CONNECT_AFTERフラグを使用して を開始」を見つけるために検索のビットを取ったが、GTK#'s FAQ(しかし、私は頻繁にリンクされていない推測)と言い、

。 これは、イベントハンドラは、イベント ハンドラが実行したときにウィジェット が更新されることを意味し、デフォルトの信号 ハンドラの後まで実行します。この 変更の副作用が、その場合には デフォルトで ないことを意味ハンドラが真を返して停止する シグナル伝搬、Gtk#eve ntsは になりません。これは、Gtk.Buttonの の例です。 button-press-eventデフォルトシグナル ハンドラは、Press イベントを送出するようにオーバーライドされています。

潜在的に混乱しますが、これは実際にはバグではありません。 Gtk.Buttonを使用すると、 というウィジェットが表示され、Button1を押すと というレスポンスでPressedイベントが発生します。 ボタンの色を変更したい場合や、 Button3のコンテキストメニューを押すと、Gtk.Buttonではない が表示されます。正しい このようなウィジェットを実装する方法は、 サブクラスGtk.Buttonになり、 のOnButtonPressEvent仮想メソッドをオーバーライドして という新しい動作を実装すると、 が望みます。「

それは、のためにでなかった場合は、 『一般市民の抗議』(良好な界面のまれ記号)、これを回避する方法はありません、サブクラスを除くによるの不足のためにC#で、時には迷惑ですGLib.ConnectBefore属性が入っています。基本的には、このイベントハンドラを最初に呼び出すと、イベントはGtk +によって悪用されません。

私はもともとは、イベントハンドラに "余分な"パラメータを渡すことについて、実績のある解決策を適用することを提案していましたが、この場合は、equalsまたはNameを使用せずにインデックスを見つけることができます文字列それは基本的に私「ふり」というラッパーデリゲートを作成nvolvesはButtonPressEventHandlerすることがなく、内部的にあなたのバックメソッドにint型を渡します。これは、コンパイルし、エラーなしで実行されますが、それは同じ問題を抱えている

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); 
    } 

、イベントが発火することはありません。デリゲート/ラムダに属性を直接入れることはできないことに気付きました。したがって、バッキングメソッドが[GLib.ConnectBefore]であっても、デリゲートはそうしないので失敗します。

最後に、のようにClickedイベントを使用できます。期待どおりに動作することを確認しました。マウスクリックでのみ発射すると思う人もいますが、実際にはスペースバーでも発砲します。

+0

私は今のところ短いハッキーな方法を取った;-) この非常に詳細な答えとあなたの投資時間ありがとう! ところで少し修正:それは[GLib.ConnectBeforeAttribute] –

+0

する必要があります実際には、いずれかの方法で動作します。 http://www.go-mono.com/docs/index.aspx?link=C%3AGtk.ButtonPressEventArgsを参照してください。私はまた、http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspxを見つけました。「慣例により、すべての属性名は「属性」という単語で終わり、他の属性名と区別することができますただし、コード内の属性を使用するときに属性サフィックスを指定する必要はありません。 –

0

私のようなもの、あなたが実際にGTKウィンドウの階層にボタンを追加する必要がありますかなり確信している:

for (uint i = 0; i < 10; i++) { 
     plus[i] = new Button(); 
     plus[i].Name = i.ToString(); 
     plus[i].ButtonPressEvent += AddButtonPressed; 
     Add(plus[i]); 
    } 

はそのようになり、実際にはGTK <を使ったことがありません。 <

+0

彼らはすべて正しくVBOXに追加し、プログラムを実行する際に示したが、ボタンを押すと動作しませんされています。 申し訳ありませんが、私はそれがはっきりしていると思った... –

+0

ああよく私は試みた! – Blindy

+0

ありがとう、;-) –

0

Gtkボタンにタグがある場合は、[タグ]プロパティを使用します。

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]); 
} 

ハンドラ:

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); 
} 
+0

まあ、Gtk.Buttonには「タグ」というプロパティはありませんが、同じ方法で動作するはずの識別子として名前を使用しようとしました。 とにかくこれは、ボタンを押したときにメソッドが呼び出されないという問題に私を助けませんが、感謝します。 –

+0

イベントハンドラの署名が間違っています。パブリックデリゲートButtonPressEventHandler(オブジェクトo、ButtonPressEventArgs args) – mnn

+0

これは間違っています。実際にテストしたかどうかを知ることができたように、「変換を委任するメソッドグループは引数の型に反則があります」(http://blogs.msdn.com/ericlippert/archive/2007/10/19/covariance-and -contravariance-in-c-part-three-member-group-conversion-variance.aspx)。 AddButtonPressedは/ any/EventArgsを受け入れるので、ButtonPressEventArgsはまったく別の種類のEventArgsなので、本来ButtonPressEventArgsを受け入れます。 –

1
for (uint i = 0; i < 10; i++) 
{ 
    plus[i] = new Button(); 
    plus[i].Data.Add("Index",i); 
    plus[i].ButtonPressEvent += AddButtonPressed; 
    Add(plus[i]); 
} 

ハンドラ:

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"]); 
} 
関連する問題