试图用特殊行为渲染Threepenny-gui中的字段 [英] Trying to render fields in threepenny-gui with special behaviour

查看:55
本文介绍了试图用特殊行为渲染Threepenny-gui中的字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想做的是设置一些字段,这些字段在焦点对准时显示详细信息,而在焦点不对准时显示摘要.例如.

What I want to do is set up fields which show detail when they're in focus, but summary when they're not. eg.

a).当它失去焦点(变得模糊?)时,我将该值保存在(状态?)映射中,然后将该值更改为旧值(即汇总值)的函数

a). when it loses focus (gets blur?), I save the value in a (State?) Map and then change the value to a function of the old value (ie. the summary value)

b).当它成为焦点时-我将摘要值替换为保存在地图中的旧值

b). when it gets focus - I replace the summary value with the old value that I saved in the Map

我不知道该怎么做,但是我想我可能需要一个状态单子和UI单子.我的尝试是:

I cant' figure out how to do this, but I think I probably need a state monad and the UI monad. My try is:

renderField :: Map->Int->UI (Element, Map)
renderField vs ix = do
    input <- UI.input  
    on UI.blur input $ \_ -> void $ do
        fieldValue <- get value input
        let newVs = insert ix fieldValue vs
        return input # set UI.value (calcNewValue fieldValue)
    on UI.focus input $ \_ -> void $ do
        let savedValue = findWithDefault "" ix vs
        return input # set UI.value savedValue
    return (input, newVs)

但是我无法使该地图正常工作-因为它需要跟踪所有呼叫....我想它应该是State monad之类的东西?

but I can't get this map to work - because it needs to track all the calls.... I guess it should be State monad or something?

谢谢.

N

推荐答案

实际上,您需要跟踪状态.

Indeed, you need to keep track of state.

但是,通常的模式s -> (a,s)(状态monad)在这里不适用,因为您正在使用回调函数.对于这些,您需要一个不同的模式.

However, the usual pattern s -> (a,s) (the state monad) does not apply here, as you are working with callback functions. For these, you need a different pattern.

在传统命令式样式中,此处将使用可变变量,例如IORef.请注意,不再需要跟踪索引-您可以将IORef视为大型可变映射中的索引.

In the traditional imperative style, one would use a mutable variable here, for instance an IORef. Note that it is no longer necessary to keep track of indices -- you can think of an IORef as being an index in a large mutable map.

renderField :: UI Element
renderField = do
    input <- UI.input
    state <- liftIO $ newIORef

    on UI.blur input $ \_ -> do
        fieldValue <- get value input
        liftIO $ writeIORef state fieldValue    
        element input # set UI.value (calcNewValue fieldValue)

    on UI.focus input $ \_ -> do
        savedValue <- liftIO $ readIORef state
        element input # set UI.value savedValue

    return input

或者,您也可以在Threepenny中使用函数式反应性编程(FRP).请注意,API仍处于初步阶段,以下代码特定于threepenny-gui版本0.4.*:

Alternatively, you can also use functional reactive programming (FRP) in Threepenny. Note that the API is still somewhat preliminary, the following code is specific to threepenny-gui version 0.4.*:

renderField :: UI Element
renderField = do
    input  <- UI.input

    bValueUser <- stepper "" $ UI.valueChange input
    bState     <- stepper "" $ bValueUser <@ UI.blur input
    bValue     <- stepper "" $ fmap head $ unions
        [ (calcNewValue <$> bValueUser) <@ UI.blur input
        , bState <@ UI.focus input
        ]
    element input # sink UI.value bValue 

再次,此代码中仍然存在一些微妙之处,但这是我想要了解的一般方向.有关FRP及其在GUI开发中的应用的一些初步信息可以在文档.

Again, there are still a couple of subtleties and warts in this code, but this is the general direction I want to head in. Some preliminary information about FRP and how it applies to GUI development can be found in the documentation.

我的建议是在需要快速完成工作时使用熟悉的解决方案(IORef),并在有大量空闲时间时使用FRP解决方案. 示例代码主要使用FRP样式.

My recommendation is to use the familiar solution (IORef) when you need to get something done quickly, and explore the FRP solution when you have plenty of free time. The example code mainly uses the FRP style.

(披露:我是Threepenny的作者.)

(Disclosure: I'm the author of Threepenny.)

这篇关于试图用特殊行为渲染Threepenny-gui中的字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆