- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个关于 Threepenny-Gui 与 StateT 交互的问题。考虑这个玩具程序,每次单击按钮时,都会在列表中添加一个“Hi”项目:
import Control.Monad
import Control.Monad.State
import qualified Graphics.UI.Threepenny as UI
import Graphics.UI.Threepenny.Core hiding (get)
main :: IO ()
main = startGUI defaultConfig setup
setup :: Window -> UI ()
setup w = void $ do
return w # set title "Ciao"
buttonAndList <- mkButtonAndList
getBody w #+ map element buttonAndList
mkButtonAndList :: UI [Element]
mkButtonAndList = do
myButton <- UI.button # set text "Click me!"
myList <- UI.ul
on UI.click myButton $ \_ -> element myList #+ [UI.li # set text "Hi"]
return [myButton, myList]
现在,我希望它打印自然数,而不是“Hi”。我知道我可以利用 UI monad 是 IO 包装器这一事实,并读取/写入我迄今为止在数据库中达到的数字,但是,出于教育目的,我想知道我是否可以使用StateT,或通过 Threepenny-gui 界面访问列表内容。
最佳答案
StateT
在这种情况下不起作用。问题是您需要在按钮回调调用之间保持计数器的状态。由于回调(以及 startGUI
)产生 UI
任何行动 StateT
使用它们运行的计算必须是独立的,以便您可以调用 runStateT
并利用结果 UI
行动。
使用 Threepenny 保持持久状态有两种主要方法。第一个也是最直接的方法是使用 IORef
(这只是一个位于 IO
中的可变变量)来保存计数器状态。这会产生与使用传统事件回调 GUI 库编写的代码非常相似的代码。
import Data.IORef
import Control.Monad.Trans (liftIO)
-- etc.
mkButtonAndList :: UI [Element]
mkButtonAndList = do
myButton <- UI.button # set text "Click me!"
myList <- UI.ul
counter <- liftIO $ newIORef (0 :: Int) -- Mutable cell initialization.
on UI.click myButton $ \_ -> do
count <- liftIO $ readIORef counter -- Reads the current value.
element myList #+ [UI.li # set text (show count)]
lift IO $ modifyIORef counter (+1) -- Increments the counter.
return [myButton, myList]
第二种方式是从命令式回调接口(interface)切换到 Reactive.Threepenny
提供的声明式FRP接口(interface).
mkButtonAndList :: UI [Element]
mkButtonAndList = do
myButton <- UI.button # set text "Click me!"
myList <- UI.ul
let eClick = UI.click myButton -- Event fired by button clicks.
eIncrement = (+1) <$ eClick -- The (+1) function is carried as event data.
bCounter <- accumB 0 eIncrement -- Accumulates the increments into a counter.
-- A separate event will carry the current value of the counter.
let eCount = bCounter <@ eClick
-- Registers a callback.
onEvent eCount $ \count ->
element myList #+ [UI.li # set text (show count)]
return [myButton, myList]
Reactive.Threepenny
的典型用法像这样:
Event
从用户输入通过 Graphics.UI.Threepenny.Events
(或 domEvent
,如果您选择的事件未包含在该模块中)。这里,“原始”输入事件是 eClick
.Control.Applicative
来处理事件数据。和Reactive.Threepenny
组合器。在我们的示例中,我们转发 eClick
如eIncrement
和eCount
,在每种情况下设置不同的事件数据。 Behavior
来利用事件数据。 (如 bCounter
)或回调(通过使用 onEvent
)。行为有点像可变变量,只不过对它的更改是由事件网络以原则性的方式指定的,而不是通过散布在代码库中的任意更新来指定的。用于处理此处未显示的行为的有用函数是 sink
函数,它允许您将 DOM 中的属性绑定(bind)到行为的值。this question 中提供了一个额外的示例,以及对这两种方法的更多评论。以及 Apfelmus 的回答。
<小时/>细节:在 FRP 版本中您可能关心的一件事是是否 eCount
将得到 bCounter
中的值eIncrement
触发更新之前或之后。答案是,该值肯定会是旧值,正如预期的那样,因为,正如 Reactive.Threepenny
中提到的那样。文档,Behavior
更新和回调触发具有名义上的延迟,而其他Event
则不会发生这种情况。操纵。
关于haskell - 混合 Threepenny-Gui 和 StateT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24117788/
使用Threepenny-gui中的“设置文本”,可以给定一个元素和一个字符串,设置该元素的文本: Prelude Graphics.UI.Threepenny.Core> :t set set ::
亲爱的 Haskell 社区,我已经编写了我的第一个 gui 应用程序并决定使用threepenny-gui 来这样做。 任务是在给定文件夹中搜索匹配的文件并提供打开这些文件的链接。此外,由于文件(大
如果我在某些 Element 上使用 delete 函数,我该如何重新创建它们(例如让它们再次出现)? 我查看了示例和文档,但找不到任何可以让我执行此操作的函数,除了 mkElement ,它需要我向
Tab 键将网格中的焦点更改为下一个元素。如何让向上/向下/向左/向右箭头键也起作用? 最佳答案 很简单,您首先确定箭头键值并在 KeyPress 上编写代码并检查键的值并编写适当的代码,然后让我知道
我有一个 Event String我想要 sink进入文本区域。这工作正常,但现在我想将复选框选择的当前值组合到这个字符串。 首先,我通过使用 checkedChange 来做到这一点有效但有问题的复
我正在学习如何使用 Threepenny GUI,我已连接到 Canvas 中的点击事件流,将该事件流映射到 Point 流并将 accumB 应用于 [] 和 Event Point 来获取 Beh
我有一个关于 Threepenny-Gui 与 StateT 交互的问题。考虑这个玩具程序,每次单击按钮时,都会在列表中添加一个“Hi”项目: import Control.Mon
我目前正在努力访问 DragData on UI.drop 时拖动元素的叫做。我有这样的事情: tile do -- How to receive the DragData here? 有人
我尝试安装 Threepenny-gui,但在此过程中可能会损坏一些东西。我的问题是(1)如何解决这个问题,以及(2)当 cabal 发出有关可能重新安装的警告时,应该如何进行? tripenny-g
我是一名优秀的程序员,十分优秀!