User interface 在计算序列项时显示序列项
我写了一个小程序,在窗口中显示斐波那契序列的前30项。但是,它不起作用。我的程序(见下文)计算所有术语,但只显示最后一个术语。我想显示所有30项,一旦计算出来。我该怎么办User interface 在计算序列项时显示序列项,user-interface,haskell,User Interface,Haskell,我写了一个小程序,在窗口中显示斐波那契序列的前30项。但是,它不起作用。我的程序(见下文)计算所有术语,但只显示最后一个术语。我想显示所有30项,一旦计算出来。我该怎么办 module Main where import Control.Monad (forM) import Graphics.UI.Gtk import Graphics.UI.Gtk.Glade fib :: Int -> Integer f
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
但这是不对的。你能帮我吗
错误是:
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)) }
GTK是单螺纹的。因此,虽然
guiAnswer
中的代码确实会在显示内容时调用labelSetText
,但在guiAnswer
返回之前,不会实际使用该数据
盲猜:尝试在labelSetText
之后运行mainContextIteration mainContextDefault False
更好的猜测:在不同的线程中运行计算。但是请注意,所有gtk交互都必须从主线程进行,因此您必须经历一些麻烦才能同步
许多年前,我为a实现了“计算发生时显示”功能,但我不确定我是否仍会提倡这种风格:-)我不熟悉您使用的库,但我希望您正在覆盖单个值,而不是累积要显示的值列表<代码>labelSetText(显示gui)(show$fib t))是的,预期的行为是在计算值时立即显示值,如果计算太快?假设所有的计算都在0.1秒内完成,它应该如何显示?这就是我使用斐波那契套件的原因;compute 30术语需要几秒钟,只有在这几秒钟之后,标签的文本才会更改。这就是我发布这条消息的原因:我认为整个套件都是在显示之前计算出来的。但你是对的:这还是有点快。如果你能将代码和所有相关文件(即
xml
文件)一起上传到某个地方,会更容易得到帮助。然后我可以很容易地测试我的建议:-)会有一些同步问题,但不会太多:gtk提供了postGUIAsync
(和postGUISync
)以实现更方便的同步。太好了。这应该是基于原始代码的直接解决方案,方法是将guiAnswer
包装在forkIO
中,并将labelSetText
包装在postGUIAsync
中。有人关心测试和发布答案吗?@loveley,别忘了把guiAnswer
(或者只是表单
行)包装在forkIO
中。对不起,我不知道怎么做。你能给我看看吗?我得到了一些关于mapM函数的错误(它需要forkIO[()]而不是forkIO())使用mapM\uuu
而不是mapM
。
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)) }