Использование сигналов GTK haskell-gi

Нуб Haskell Gi-GTK здесь. И GTK нуб в целом.

У меня есть изображение, которое я завернул в Eventbox. Теперь я хочу определить, когда пользователь нажимает на поле события (нажатие мыши). Некоторые гуглы указывают мне на использование button-press-event. Мой код ниже.

drag <- imageNewFromFile "rszh.png"
dragevents <- eventBoxNew
containerAdd dragevents drag
set dragevents [widgetHalign := AlignEnd, widgetValign := AlignEnd]
onWidgetButtonPressEvent dragevents (print "Hello world")

И GHC не может скомпилировать это со следующим загадочным сообщением об ошибке:

panedraggin.hs:30:42: error:
    • Couldn't match type ‘IO ()’
                     with ‘GI.Gdk.Structs.EventButton.EventButton -> IO Bool’
      Expected type: GI.Gtk.Objects.Widget.WidgetButtonPressEventCallback
        Actual type: IO ()
    • Possible cause: ‘print’ is applied to too many arguments
      In the second argument of ‘onWidgetButtonPressEvent’, namely
        ‘(print "Hello world")’
      In a stmt of a 'do' block:
        onWidgetButtonPressEvent dragevents (print "Hello world")
      In the expression:
        do { Gtk.init Nothing;
             window <- windowNew WindowTypeToplevel;
             onWidgetDestroy window mainQuit;
             windowMaximize window;
             .... }

Что я делаю неправильно?


person hello    schedule 25.06.2017    source источник
comment
Вы используете print ... в качестве обработчика событий, но предполагается, что это функция, принимающая информацию о том, какая кнопка была нажата и т.д. и возвращает IO Bool, где логическое значение указывает, удалось ли обработчику.   -  person chi    schedule 25.06.2017
comment
Я посмотрел на пример gi-gtk hello world за помощью. В строке 30 они использовали onButtonClicked button (putStrLn "Hello World") для сигналов. Этот код работает без ошибок. В чем разница между моим кодом и их кодом? Я запустил :t для обеих функций в ghci, и единственная разница в их сигнатурах типов заключается в том, что одна принимает ButtonClickedCallback в качестве параметра, а другая принимает WidgetButtonPressEventCallback. Изменение моего оператора печати на функцию putStrLn по-прежнему дает мне ту же ошибку.   -  person hello    schedule 25.06.2017
comment
Я не эксперт по gtk+, но полагаю, что один реагирует на клики, а другой — на нажатия кнопок мыши, которые могут быть кликами, а могут и не быть, поскольку на наших мышах много кнопок. Следовательно, четный обработчик в последнем случае принимает аргумент, указывающий, какая кнопка была нажата и т. д.   -  person chi    schedule 25.06.2017


Ответы (1)


Ну, в сообщении об ошибке уже сказано: ожидается функция типа EventButton -> IO Bool, а print "Hello world" имеет тип IO ().

Однако вы можете легко превратить его в один с помощью:

onWidgetButtonPressEvent dragevents (const $ print "Hello world" >> return True)

Таким образом, используя const $, мы пока игнорируем параметр EventButton (позже вы можете решить принять во внимание параметры события), а используя >> return True, мы гарантируем, что после печати мы вернем True (что означает, что обратный вызов выполнен успешно).

person Willem Van Onsem    schedule 25.06.2017