GTK+ DoubleClick vs SingleClick (Как правильно обработать события)

Модератор: Модераторы разделов

Аватара пользователя
alkesta
Сообщения: 345
ОС: Fedora

GTK+ DoubleClick vs SingleClick

Сообщение alkesta »

При обработке события GdkEventType GDK_2BUTTON_PRESS сначала ренерируется собитие GDK_BUTTON_PRESS

Вопрос, как правильно обработать события двоного нажатия мыши так, чтобы выполнялось условие только для GDK_2BUTTON_PRESS и не выполнялось для GDK_BUTTON_PRESS и наоборот?

Сейчас при двойном клике выполняются - команда для двойного клика и 2 раза комада для одинарного клика
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: GTK+ DoubleClick vs SingleClick

Сообщение NickLion »

1. В структуре

Код: Выделить всё

typedef struct {
  GdkEventType type;
  GdkWindow *window;
  gint8 send_event;
  guint32 time;
  gdouble x;
  gdouble y;
  gdouble *axes;
  guint state;
  guint button;
  GdkDevice *device;
  gdouble x_root, y_root;
} GdkEventButton;

можно использовать параметр time (у GDK_BUTTON_PRESS и GDK_2BUTTON_PRESS он в этом случае будет одинаковым). Т.е. в GDK_BUTTON_PRESS прочитать следующее сообщение (не забирая из очереди) и если это двойной клик - то ничего не делать. Время может и не надо проверять даже.
2. Если вам нужен клик (нажатие-отпускание), то можно реакцию поместить в отпускание, а т.к. порядок:
  • GDK_BUTTON_PRESS
  • GDK_BUTTON_RELEASE
  • GDK_BUTTON_PRESS
  • GDK_2BUTTON_PRESS
  • GDK_BUTTON_RELEASE
  • GDK_BUTTON_PRESS
  • GDK_3BUTTON_PRESS
  • GDK_BUTTON_RELEASE

то GDK_BUTTON_RELEASE после GDK_2BUTTON_PRESS можно игнорировать (флаг использовать к примеру).

PS может в GDK есть для этого специальный прием - не в курсе
Спасибо сказали:
Аватара пользователя
BlackStar
Сообщения: 1338
Статус: We are all Kosh
ОС: Fedora 10

Re: GTK+ DoubleClick vs SingleClick

Сообщение BlackStar »

Код: Выделить всё

if (type == GDK_2BUTTON_PRESS) {
  on_double_clicked_action();
}

не?
LightLang Team
Спасибо сказали:
Аватара пользователя
alkesta
Сообщения: 345
ОС: Fedora

Re: GTK+ DoubleClick vs SingleClick

Сообщение alkesta »

Не понятен ни первый вариант, ни второй

NickLion писал(а):
26.03.2009 16:11
1. можно использовать параметр time (у GDK_BUTTON_PRESS и GDK_2BUTTON_PRESS он в этом случае будет одинаковым). Т.е. в GDK_BUTTON_PRESS прочитать следующее сообщение (не забирая из очереди) и если это двойной клик - то ничего не делать. Время может и не надо проверять даже.

как время события отражается на GDK_BUTTON_PRESS и GDK_2BUTTON_PRESS?
Все равно же будет
  • GDK_BUTTON_PRESS
  • GDK_BUTTON_PRESS
  • GDK_2BUTTON_PRESS

и сотвествено обработка двойного клика, как - один клик, один клик, двойной клик

NickLion писал(а):
26.03.2009 16:11
2. Если вам нужен клик (нажатие-отпускание), то можно реакцию поместить в отпускание, а т.к. порядок:
  • GDK_BUTTON_PRESS
  • GDK_BUTTON_RELEASE
  • GDK_BUTTON_PRESS
  • GDK_2BUTTON_PRESS
  • GDK_BUTTON_RELEASE
  • GDK_BUTTON_PRESS
  • GDK_3BUTTON_PRESS
  • GDK_BUTTON_RELEASE

то GDK_BUTTON_RELEASE после GDK_2BUTTON_PRESS можно игнорировать (флаг использовать к примеру).

Не понятно ничего. Можно по подробнее

(BlackStar) писал(а):не?

не, вопрос не в этом

Повторюсь, нужно чтоб по двойному клику выполнялось действие BBB, по одинарному клику действие AAA.
Сейчас же имею:
один клик - действие AAA (все нормально)
двойной клик - действие AAA, действие AAA, действие BBB (а нужно только действие BBB)
Спасибо сказали:
Аватара пользователя
BlackStar
Сообщения: 1338
Статус: We are all Kosh
ОС: Fedora 10

Re: GTK+ DoubleClick vs SingleClick

Сообщение BlackStar »

Еще раз:

Код: Выделить всё

on_ clicked(... GdkEventButton * event ...) {
 if (event->type == GDK_2BUTTON_PRESS) {
     BBB
 } else {
     AAA
 }
}
LightLang Team
Спасибо сказали:
Аватара пользователя
alkesta
Сообщения: 345
ОС: Fedora

Re: GTK+ DoubleClick vs SingleClick

Сообщение alkesta »

BlackStar писал(а):
26.03.2009 18:43
Еще раз:

Код: Выделить всё

on_ clicked(... GdkEventButton * event ...) {
 if (event->type == GDK_2BUTTON_PRESS) {
     BBB
 } else {
     AAA
 }
}

Этот код архилогичен, но при двойном клике будет выполнено:
ААА, ААА, ВВВ.
Потому как:
1/ GDK_BUTTON_PRESS
условие - ложь, будет выпонено else {}, т.е. ААА
2/ GDK_BUTTON_RELEASE
3/ GDK_BUTTON_PRESS
условие - ложь, будет выпонено else {}, т.е. ААА
4/ GDK_2BUTTON_PRESS
условие - истина, будет выпонено BBB

Собственно именно в этом и вопрос:
Как при двойном клике выполнить только ВВВ?
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: GTK+ DoubleClick vs SingleClick

Сообщение NickLion »

1. При получении GDK_BUTTON_PRESS смотрите какое следующее событие - если это GDK_2BUTTON_PRESS (вот здесь для особо замороченных людей вроде меня я и предлагал проверить соответствие времени), то игнорируете GDK_BUTTON_PRESS.
2. Вообще игнорируете GDK_BUTTON_PRESS, а обработка при получении GDK_BUTTON_RELEASE, но полезные действия только если флаг=0, а в конце в любом случае флаг сбрасываете в 0. При получении GDK_2BUTTON_PRESS делаете нужное Вам, и устанавливаете флаг=1.
Спасибо сказали:
Аватара пользователя
sergeyvp
Сообщения: 807
ОС: ubuntu

Re: GTK+ DoubleClick vs SingleClick

Сообщение sergeyvp »

Что то мне кажется что это неразрешимая задача.
Сигнал нажатия на кнопку первичен для определения двойного клика поэтому его игнорировать не получиться.
Функция при нажатии будет выполняться в любом случае, поэтому можно написать хитрый обработчик который будет перед выполнением функции проверять не являлось ли нажатие составным сигналом двойного клика а для этого нужно выдержать определённую паузу, но это только лишняя трата времени по моему.

цепочка сигналов при двойном клике
1. GDK_BUTTON_PRESS
2. GDK_BUTTON_RELEASE
3. GDK_BUTTON_PRESS
4. GDK_2BUTTON_PRESS
5. GDK_BUTTON_RELEASE

можно сделать примерно так

нажатие
val = TRUE
функция с паузой (должна превышать паузу между кликами)
если TRUE выполнение

двойной клик
val = FALSE

таким образом во время двойного клика функции отправляются в режим ожидания и если двойной клик обнуляет переменную значит они не выполняются.
Спасибо сказали:
Аватара пользователя
alkesta
Сообщения: 345
ОС: Fedora

Re: GTK+ DoubleClick vs SingleClick

Сообщение alkesta »

NickLion писал(а):
27.03.2009 09:04
1. При получении GDK_BUTTON_PRESS смотрите какое следующее событие - если это GDK_2BUTTON_PRESS (вот здесь для особо замороченных людей вроде меня я и предлагал проверить соответствие времени), то игнорируете GDK_BUTTON_PRESS.

Каким средствами это делается? проверить соответствие времени чему? Как смотреть следующее событие?

NickLion писал(а):
27.03.2009 09:04
2. Вообще игнорируете GDK_BUTTON_PRESS, а обработка при получении GDK_BUTTON_RELEASE, но полезные действия только если флаг=0, а в конце в любом случае флаг сбрасываете в 0. При получении GDK_2BUTTON_PRESS делаете нужное Вам, и устанавливаете флаг=1.

Но ведь GDK_BUTTON_RELEASE следует и за GDK_BUTTON_PRESS и за GDK_2BUTTON_PRESS

Если можно, то хотя бы псевдокод напишите пожалуйста, пока не понимаю логики выше сказанного :unsure:
Спасибо сказали:
Аватара пользователя
alkesta
Сообщения: 345
ОС: Fedora

Re: GTK+ DoubleClick vs SingleClick

Сообщение alkesta »

sergeyvp писал(а):
27.03.2009 12:34
нажатие
val = TRUE
функция с паузой (должна превышать паузу между кликами)
если TRUE выполнение

двойной клик
val = FALSE


Правильно ли я понимаю:

Код: Выделить всё

on_clicked (... GdkEventButton...) {
val = TRUE;
delay (чуть больше 1/4 секунды);
if (event->type == GDK_2BUTTON_PRESS)
    {
     val = FALSE;
     BBB();
     }
 else
    {
     if (val == TRUE)
             AAA();
     }
}
Спасибо сказали:
Аватара пользователя
sergeyvp
Сообщения: 807
ОС: ubuntu

Re: GTK+ DoubleClick vs SingleClick

Сообщение sergeyvp »

alkesta писал(а):
27.03.2009 14:39
Правильно ли я понимаю:

Код: Выделить всё

on_clicked (... GdkEventButton...) {
val = TRUE;
delay (чуть больше 1/4 секунды);
if (event->type == GDK_2BUTTON_PRESS)
    {
     val = FALSE;
     BBB();
     }
 else
    {
     if (val == TRUE)
             AAA();
     }
}


Нет немного не так.
Функция ААА запускается в любом случае, но в теле функции стоит пауза и затем проверка переменной, если переменная после паузы TRUE значит двойного клика небыло и соответственно можно выполнять содержимое функции ААА.

Код: Выделить всё

on_clicked (... GdkEventButton...) {
if (event->type == GDK_2BUTTON_PRESS)
    {
     val = FALSE;
     BBB();
     }
 else
    {
     val = TRUE;
     AAA()
              {
                 delay(1/4);
                 if(val == TRUE)
                                  {
                                    основной код функции;
                                   }
              };
     }
}
Спасибо сказали:
Аватара пользователя
alkesta
Сообщения: 345
ОС: Fedora

Re: GTK+ DoubleClick vs SingleClick

Сообщение alkesta »

Не понятно, возможно Вы хотели сказать это:

Код: Выделить всё

on_clicked (... GdkEventButton...) {
if (event->type == GDK_2BUTTON_PRESS)
    {
     val = FALSE;
     BBB();
     }
 else
    {
     val = TRUE;
     AAA();
     }
}
AAA(void){
     delay(1/4);
     if(val == TRUE) /*val глобальная или значение получается по ссылке на val*/
          {
             основной код функции;
           }
 }
Спасибо сказали:
Аватара пользователя
sergeyvp
Сообщения: 807
ОС: ubuntu

Re: GTK+ DoubleClick vs SingleClick

Сообщение sergeyvp »

alkesta писал(а):
27.03.2009 15:58
Не понятно, возможно Вы хотели сказать это:

Код: Выделить всё

on_clicked (... GdkEventButton...) {
if (event->type == GDK_2BUTTON_PRESS)
    {
     val = FALSE;
     BBB();
     }
 else
    {
     val = TRUE;
     AAA();
     }
}
AAA(void){
     delay(1/4);
     if(val == TRUE) /*val глобальная или значение получается по ссылке на val*/
          {
             основной код функции;
           }
 }

Ну да, просто я функцию выносить не стал, это же всё равно псевдокод :)
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: GTK+ DoubleClick vs SingleClick

Сообщение NickLion »

1 вариант. Имелось в виду:

Код: Выделить всё

if( event->type == GDK_BUTTON_PRESS ) {
    event2 = следующее сообщение из очереди; // но оставить его в очереди
    if( event2->type == GDK_2BUTTON_PRESS /* && event2->time == event->time */ )
    {
        забрать сообщение из очереди;
        выполнить действие для двойного клика;
    } else {
        выполнить действие обычного клика;
    }
}


2. Имелось в виду:

Код: Выделить всё

обработка GDK_BUTTON_PRESS { flag = 0; }
обработка GDK_2BUTTON_PRESS {
    flag = 1;
    обработка двойного клика;
}
обработка GDK_BUTTON_RELEASE {
    if( !flag ) {
        обработка одинарного клика;
    }
    flag = 0;
}
Спасибо сказали:
Аватара пользователя
alkesta
Сообщения: 345
ОС: Fedora

Re: GTK+ DoubleClick vs SingleClick

Сообщение alkesta »

NickLion писал(а):
27.03.2009 19:25
2. Имелось в виду:

Код: Выделить всё

обработка GDK_BUTTON_PRESS { flag = 0; }
обработка GDK_2BUTTON_PRESS {
    flag = 1;
    обработка двойного клика;
}
обработка GDK_BUTTON_RELEASE {
    if( !flag ) {
        обработка одинарного клика;
    }
    flag = 0;
}


При двойном клике получается:
1. GDK_BUTTON_PRESS установка flag = 0
2. GDK_BUTTON_RELEASE flag == 0 условие верно | {исполняется код обработки одинарного клика} | установка flag = 0
3. GDK_BUTTON_PRESS установка flag = 0
4. GDK_2BUTTON_PRESS {исполняется код обработки двойного клика} | установка flag = 1
5. GDK_BUTTON_RELEASE flag == 1 условие не верно | устанановка flag = 0
т.е. при двойном клике {исполняется код обработки одинарного клика} и {исполняется код обработки двойного клика}. Или я что-то не так понимаю?
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: GTK+ DoubleClick vs SingleClick

Сообщение NickLion »

Перечитал тему, я Вас тогда не понял. Я думал, что проблема в повторной обработке одинарного нажатия. Если нужно, чтобы при двойном клике не был обработан даже первый клик, то единственный выход - задержка по времени перед обработкой нажатия (как говорил sergeyvp), т.к. в момент первого нажатия система не может знать - будет второй клик или нет. Хотя имхо - надо передумать интерфейс. Это нелогичное поведение. Плюс к тому же - мы обычно пользуемся не системами реального времени, поэтому что произойдет раньше, а что позже - вопрос не всегда явный. Как бы не замучаться с этими таймерами/задержками.
Задержка должна быть не менее 1/4 секунды (хм... это не настраиваемый параметр? странно...):
For a double click to occur, the second button press must occur within 1/4 of a second of the first. For a triple click to occur, the third button press must also occur within 1/2 second of the first button press.
Спасибо сказали: