C #: Получить, какая кнопка была нажата в массиве кнопок gtk #? - PullRequest
1 голос
/ 25 мая 2009

У меня есть массив кнопок, которые должны вызывать один и тот же метод, но с индексом кнопки в качестве аргумента.

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

Может быть, кто-то может указать мне правильное направление? Благодаря.

Ответы [ 4 ]

3 голосов
/ 25 мая 2009

Быстрый ответ:

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

Разъяснение:

Это на самом деле интересный вопрос. Потребовалось немного поиска, чтобы найти, но FAQ по GTK # (но я думаю, что это не часто связано с) говорит,

"Начиная с версии 0.15, Gtk # запущен используя флаг CONNECT_AFTER, когда подключение обработчиков событий к сигналам. Это означает, что обработчики событий не запускается до тех пор, пока не будет получен сигнал по умолчанию обработчики, что означает, что виджет будет обновлено, когда событие обработчики бегут. Побочный эффект этого изменение заключается в том, что в случае, когда обработчики по умолчанию возвращают true для остановки сигнал распространения, Gtk # события будут не будет выброшено Это случай для пример в Gtk.Button, где сигнал нажатия кнопки по умолчанию обработчик переопределен для выдачи Pressed события.

Хотя это может сбивать с толку, это не совсем ошибка. Когда вы используете Gtk.Button, вы получаете виджет который генерирует Pressed-события в ответ на Button1 нажимает. Если вы тоже хотите ваша кнопка, чтобы изменить цвета, или всплывающее окно контекстное меню на нажатия кнопок Button3, это не Gtk.Button. Правильный способ реализовать такой виджет заключается в подкласс Gtk.Button и переопределить OnButtonPressEvent виртуальный метод для реализовать новое поведение, которое вы желание. "

Если бы не «общественный резонанс» (редко признак хорошего интерфейса), не было бы способа избежать этого, кроме подклассов, которые иногда раздражают в C # из-за отсутствия анонимных классов. Но, к счастью, вы не первый человек, который имеет эту проблему. Так вот, где вступает атрибут GLib.ConnectBefore. По сути, он говорит: сначала вызовите этот обработчик событий, чтобы Gtk + не поглощал событие.

Но раздражение на этом не заканчивается. Первоначально я собирался предложить хорошее проверенное решение для передачи «дополнительных» параметров обработчикам событий. В этом случае это позволит вам найти индекс без использования равенства или строки Name. В основном это включает создание делегата-оболочки, который «притворяется» 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, как в в этом примере API . Я проверил, что это работает как ожидалось. Можно подумать, что он будет срабатывать только при щелчках мышью, но на самом деле он также срабатывает и по пробелу.

1 голос
/ 11 мая 2011
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"]);
}
0 голосов
/ 25 мая 2009

Использовать свойство Tag, если оно есть у кнопки 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 голосов
/ 25 мая 2009

Я вполне уверен, что вам нужно добавить кнопки в иерархию окон 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 <. <</p>

...