在计算序列时显示它们的术语

时间:2015-11-20 12:43:02

标签: user-interface haskell

我写了一个小程序,在窗口中显示Fibonacci序列的前30个项。但是,它不起作用。我的程序(见下文)计算所有术语,但只显示最后一个术语。我想在计算后立即显示所有30个术语。我该怎么办?

module Main where

import           Control.Monad         (forM)
import           Graphics.UI.Gtk
import           Graphics.UI.Gtk.Glade

fib :: Int -> Integer
fib 1 = 1
fib 2 = 1
fib n = fib(n-1)+fib(n-2)

data GUI = GUI {
  mainWin :: Window,
  clickMe :: Button,
  display :: Label
  }

loadGlade :: IO GUI
loadGlade = do
  Just xml <- xmlNew "gladeFile.glade"
  mw <- xmlGetWidget xml castToWindow "wdwFirst"
  bc <- xmlGetWidget xml castToButton "btnClick"
  ld <- xmlGetWidget xml castToLabel "lblDisplay"

  return $ GUI mw bc ld

connectGui :: GUI -> IO  (ConnectId Button)
connectGui gui = do
  onDestroy (mainWin gui) mainQuit
  onClicked (clickMe gui) (guiAnswer gui)

guiAnswer :: GUI -> IO()
guiAnswer gui = do
  a<-forM [1..30] (\t -> labelSetText (display gui) (show $ fib t))
  --labelSetText (display gui) "WELCOME!!"
  putStr ""


main :: IO ()
main = do
  initGUI
  gui <- loadGlade
  connectGui gui
  widgetShowAll (mainWin gui)
  mainGUI

编辑:

对于postGuiAsync,我试过这个:

guiAnswer :: GUI -> IO()
guiAnswer gui = do
  a<-forM [1..40] (\t -> postGUIAsync $ labelSetText (display gui) (show $ fib t))
  --labelSetText (display gui) "WELCOME!!"
  --mainContextIteration mainContextDefault False
  print ""

但没有成功(它仍然只显示最终的数字),我不确定我的代码。

EDIT2: 我试过这个:

guiAnswer :: GUI -> IO()
guiAnswer gui = do
  forkIO $ forM_ [1..40] (\t -> postGUIAsync $ labelSetText (display gui) (show $ fib t))

但这不正确。你能帮助我吗?

错误是:

Couldn't match type `GHC.Conc.Sync.ThreadId' with `()'
 Expected type: IO ()
   Actual type: IO GHC.Conc.Sync.ThreadId
 In a stmt of a 'do' block:
   forkIO
   $ forM_
       [1 .. 40]
       (\ t -> postGUIAsync $ labelSetText (display gui) (show $ fib t))
 In the expression:
   do { forkIO
        $ forM_
            [1 .. 40]
            (\ t -> postGUIAsync $ labelSetText (display gui) (show $ fib t)) }

1 个答案:

答案 0 :(得分:2)

GTK是单线程的。因此,虽然guiAnswer中的代码确实会在显示内容时调用labelSetText,但在guiAnswer返回之前,实际上不会使用该数据。

盲目猜测:尝试在mainContextIteration mainContextDefault False后运行labelSetText

更好的猜测:在不同的线程中运行计算。但要注意所有gtk交互必须从主线程发生,所以你将不得不经历一些麻烦来同步它。

很多年前,我为fractal renderer实现了这样一种计算显示功能,但我不确定我是否仍然提倡这种风格: - )