Чего бы я хотел достичь:
Каждый раз, когда пользователь нажимает на холст, берите координаты мыши из этого щелчка, чтобы создать Point x y
и сохранить это состояние в [Point]
так, чтобы в в более поздний момент времени, когда пользователь нажимает кнопку, я могу использовать [Point]
в качестве ввода для некоторой функции.
Что я сделал:
Я определил Point
данные типа, с конструктором с одним значением, например:
data Point = Point {
x :: Int,
y :: Int
} deriving (Show, Eq)
Я установил трехпенни UI
(монада?) для определения пользовательского интерфейса, простые 400 x 400 canvas
и button
:
import qualified Graphics.UI.Threepenny as UI
import Graphics.UI.Threepenny.Core
import Control.Monad
canvasSize = 400
setup :: Window -> UI ()
setup window = do
return window # set title "Haskell GUI"
canvas <- UI.canvas
# set UI.height canvasSize
# set UI.width canvasSize
# set style [("border", "solid black 1px"), ("background", "#eee")]
button <- UI.button #+ [string "Do stuff"]
getBody window #+
[
column [element canvas],
element canvas,
element button
]
on UI.mousedown canvas $ \(x, y) -> do
-- Need to create a point x y and add it to a list here
on UI.click button $ const $ do
-- Need to get the list of points here
return ()
А затем определили функцию для запуска пользовательского интерфейса в main:
runGui :: IO ()
runGui = startGUI defaultConfig setup
Итак, изначально я работал над точками рисования в том месте, где щелкнул пользователь. Я добился этого довольно легко, построив Point x y
в аргументе lambda в mousedown
и нарисовав его там. Я опускаю этот код, поскольку я решил это, и я не верю, что моя текущая проблема связана с этим (т.е. построение и рисование точки в области действия этой лямбды).
Вместо рисования, а затем выбрасывания Point
привязанный к объему этой лямбды, я просто хотел бы сохранить эту точку в списке. Затем я хотел бы иметь возможность читать этот список, когда пользователь нажимает кнопку.
Я провел небольшое исследование Behaviour
и Event
(http://hackage.haskell.org/package/threepenny-gui-0.4.2.0/docs/Reactive-Threepenny.html ) для стиля FRP, который, как я понимаю, является чем-то, что помогает создать что-то вроде шаблона редукса, но мой мозг начинает таять.
Основано на другом посте StackOverflow ( Mixing Threepenny- * 1051) * и StateT ) Я понял, что должен подключить события пользовательского интерфейса Threepenny для создания потока событий, затем использовать accumB
для накопления каждого события из этого потока в поток некоторого поведения состояния, а затем преобразовать это Поведение состояния обратно в поток событий с применением и наблюдением в этом последнем потоке для обновления пользовательского интерфейса (я думаю, просто ... xD)
По крайней мере, это то, что я собрал, я проверил код в ответе на связанный вопрос StackOverflow, и он решил проблему, поставленную в этом конкретном вопросе. Но мне нужно зафиксировать положение мыши x y
в потоке событий mousedown
(который не был описан в этом фрагменте) и использовать его для создания потока Point
, и вот где я застрял. Я пытался реализовать его, основываясь на изменении принятого кода ответов для своих целей, но столкнулся с множеством ошибок типа, потому что я явно неправильно понимаю, как части сочетаются друг с другом.
Вот моя попытка изменить код в принятом ответе на связанный вопрос StackOverflow:
-- This *should* be the bit that converts
-- (x, y) click events to Point x y Event stream
let canvasClick = UI.mousedown canvas
newPointStream = (\(x, y) -> Point x y) <$ (canvasClick)
-- This *should* be the bit that turns the
-- Point x y Event stream into a "behaviour" stream
counter <- accumB (Point 0 0) newPointStream
Может ли кто-нибудь пролить свет? Я у стены: - (