1

からクラスを派生させようとしていますGtk.Button。(まったく使用しないことで)回避できる障害に遭遇しましたOnActivateが、説明できないため、回避することは安全ではない可能性があります。

から継承するOnActivateメソッドをオーバーライドすると、ボタンの挙動が変わるようです。Gtk.ButtonGtk.Widget

それはなぜですか、どうすればそれを防ぐことができますか?

そのような効果を達成する唯一の方法は、醜い反射ベースのチェックです。


これがまさに私がしたことであり、問​​題を再現するために試すことができることです:

これは、カスタム ボタン クラスとそのクラスの 1 つのインスタンスを含む Gtk# アプリケーションの小さなサンプルです。OnActivateカスタム ボタン クラスではオーバーライドされません。

using System;

using Gtk;

namespace ButtonOnActivateExample
{
    class Program
    {
        private class MyButton : Button
        {
            public MyButton()
            {
            }

            public MyButton(IntPtr raw)
            {
            }
        }

        [STAThread]
        public static void Main(string[] args)
        {
            Application.Init();
            using (Window win = new Window("OnActivate Test")) {
                win.SetSizeRequest(300, 200);
                win.Hidden += delegate(object sender, EventArgs e) {
                    Application.Quit();
                };

                MyButton btn = new MyButton();
                btn.Clicked += delegate {
                    Console.WriteLine("clicked");
                };
                win.Add(btn);

                win.ShowAll();
                Application.Run();
                win.Destroy();
            }
        }
    }
}

ボタンをクリックすると、クリックされた単語がコンソールの新しい行に追加されます。ボタンがフォーカスされている場合 (ウィンドウ内の唯一のフォーカス可能な要素であるため、通常はそうです)、ユーザーがスペースバーを押すと、予想どおり、同じことが起こります (つまり、Clickedイベントが発生します)。


この変更されたバージョンでは、わずかな変更があります。MyButtonクラスはOnActivateメソッドをオーバーライドするようになりましたが、オーバーライドされたバージョンはメソッドの継承されたバージョンを呼び出す以外には何もしません。

using System;

using Gtk;

namespace ButtonOnActivateExample
{
    class Program
    {
        private class MyButton : Button
        {
            public MyButton()
            {
            }

            public MyButton(IntPtr raw)
            {
            }

            protected override void OnActivate()
            {
                base.OnActivate();
            }
        }

        [STAThread]
        public static void Main(string[] args)
        {
            Application.Init();
            using (Window win = new Window("OnActivate Test")) {
                win.SetSizeRequest(300, 200);
                win.Hidden += delegate(object sender, EventArgs e) {
                    Application.Quit();
                };

                MyButton btn = new MyButton();
                btn.Clicked += delegate {
                    Console.WriteLine("clicked");
                };
                win.Add(btn);

                win.ShowAll();
                Application.Run();
                win.Destroy();
            }
        }
    }
}

これは、最初のバージョンと意味的に同じである必要があります。しかし、そうではありません - 不可解なことに、アプリケーションの動作が変更されました!

ドキュメントには、「OnActivateサブクラスでこのメソッドをオーバーライドして、ウィジェットがアクティブ化されたときに通知されるようにします。通常、キー ナビゲーション中にユーザーが Enter キーまたは Space キーを押したときに通知されます。」

ボタンをクリックすると、Clickedイベントが発生します。ただし、スペース バーを押しても効果がなくなります。コンソールには何も表示されません。

この動作は、.NET の Gtk#、Windows 7 の Mono、Ubuntu の Mono で一貫して再現できました。

ここで何が起こっているのですか?

4

1 に答える 1

1

それは興味深い質問です。残念ながら、正確な原因について明確な答えを出すことはできません。gtk# のソースを調べたにもかかわらず、デフォルトのシグナル ハンドラ、クラス、および gtypes のジャングルですぐに迷子になりました。

OnActivatedただし、解決策を探しているだけの場合は、メソッドをオーバーライドする必要があると言えます(d末尾に a を付けます)。

于 2013-01-26T23:53:49.210 に答える