4

したがって、リストボックス、ボタン、テキストエリアを備えた簡単なレイアウトの例があります。ボタンをクリックすると、テキストエリアのテキストが変更されます。

import Control.Applicative
import Control.Monad
import Data.Maybe

import qualified Graphics.UI.Threepenny as UI
import Graphics.UI.Threepenny.Core

main :: IO ()
main = startGUI defaultConfig setup

setup :: Window -> UI ()
setup w = do
    return w # set UI.title "Simple example"

    listBox     <- UI.listBox   (pure ["First", "Second"]) (pure Nothing) ((UI.string .) <$> (pure id))
    button      <- UI.button    # set UI.text "Button"
    display     <- UI.textarea  # set UI.text "Initial value"

    element listBox # set (attr "size") "10"    

    getBody w   #+ [element listBox, element button, element display]

    on UI.click button $ const $ do
        element display # set UI.text "new text"

私がやりたかったのは、変更をリストボックスの選択に依存させることです(たとえば、選択に基づいて変更する"new text"か、"First"または"Second"選択に基づいて変更します)。

userSelectionfactsを組み合わせることで、非常に簡単に選択を取得できます

facts . userSelection :: ListBox a -> Behavior (Maybe a)

しかし、テキストエリアの値の設定は

set text :: String -> UI Element -> UI Element

選択がBehavior.

これはすべて私には少し単調に思えます.これを行う正しい方法は何だろうと思っていました. ボタンが押されたときだけでなく、リストボックスの選択が完了または変更されたときに、何かをする必要があるかもしれません。

4

3 に答える 3

4

まず第一に、ここのコードに影響を与えるリグレッションがありました。その問題は解決されました。Threepenny 0.6.0.3 には一時的な修正が含まれており、最終的な修正はその後のリリースに含まれます。


あなたが提供したペーストビンのコードはほぼ正しいです。sink唯一必要な変更は、ボタン クリック コールバック内で使用する必要がないことです。この場合、sink動作とテキスト領域のコンテンツの間に永続的な接続を確立し、ボタンのクリックに応じて動作値が変化する必要があります。イベント。

完全を期すために、完全な解決策を次に示します。

{-# LANGUAGE RecursiveDo #-}
module Main where

import Control.Applicative
import Control.Monad
import Data.Maybe

import qualified Graphics.UI.Threepenny as UI
import Graphics.UI.Threepenny.Core

main :: IO ()
main = startGUI defaultConfig setup

setup :: Window -> UI ()
setup w = void $ mdo
    return w # set UI.title "Simple example"

    listBox <- UI.listBox
        (pure ["First", "Second"]) bSelected (pure $ UI.string)
    button  <- UI.button # set UI.text "Button"
    display <- UI.textarea

    element listBox # set (attr "size") "10"

    getBody w #+ [element listBox, element button, element display]

    bSelected <- stepper Nothing $ rumors (UI.userSelection listBox)
    let eClick = UI.click button
        eValue = fromMaybe "No selection" <$> bSelected <@ eClick
    bValue    <- stepper "Initial value" eValue

    element display # sink UI.text bValue

重要な点は次の 2 つです。

  • へのBehavior (Maybe a)引数listBoxは、最初に選択された値を設定するだけでなく、アプリケーションの存続期間中の値の進化を決定します。この例では、モジュールのソース コードから確認できるように、facts $ UI.userSelection listBoxは単なるです。bSelectedWidgets
  • イベントの発生時に動作をサンプリングする一般的な方法は、(<@)(または<@>、使用したいデータがイベントに含まれている場合) を使用することです。
于 2015-06-19T17:31:05.830 に答える
1

リストボックスのステッパーを作成してから、シンクして表示してみてください

listB <- stepper Nothing (userSelection listBox)
element display # sink UI.text ((maybe "new text" id) <$> (listB) 

次に、ボタンで動作をサンプリングしたい場合

listB <- stepper Nothing (userSelection listBox)
button      <- UI.button    # set UI.text "Button"
cutedListB <- stepper Nothing (listB <@ UI.click button)
element display # sink UI.text ((maybe "new text" id) <$> (listB) 
于 2015-06-15T20:21:30.197 に答える