haskell & Gtk2hs : canvas 中没有显示点(平行图)
haskell & Gtk2hs : no point is displayed in a canvas (parallel drawing)
我在 haskell 中使用 Gtk2Hs 编写了一个必须显示 mandelbrot 集的小程序。
以为没有编译错误,在canvas(点被着色的组件)中什么也没有显示...
你能帮我调试一下这个逻辑错误吗?
我的代码:
module Main where
import Control.Monad (when)
import Graphics.Rendering.Cairo as C
import Graphics.UI.Gtk
import Graphics.UI.Gtk.Builder ()
main :: IO()
main = do
_ <- initGUI
builder <- builderNew
builderAddFromFile builder "09-mandelbrot.ui"
window <- builderGetObject builder castToWindow "Figure de Mandelbrot"
canvas <- builderGetObject builder castToDrawingArea "drawingarea1"
_ <- onExpose canvas $ const (updateCanvas canvas)
widgetShowAll window
mainGUI
updateCanvas :: DrawingArea -> IO Bool
updateCanvas canvas = do
win <- widgetGetDrawWindow canvas
(width, height) <- widgetGetSize canvas
_ <- mapM_ (affiche win) (points (fromIntegral width) (fromIntegral height))
return True
k :: Int
k=100
mandelbrot :: Double -> Double -> Bool
mandelbrot a b =
let
mandelrec :: Double -> Double -> Int -> Bool
mandelrec x y i
| (x * x + y * y > 4) = False
| (i==k) && (x * x + y * y <= 4) = True
| otherwise = mandelrec x' y' (i+1)
where x' = x * x - y * y + a
y' = 2 * x * y + b
in mandelrec 0 0 0
affiche2 :: DrawWindow -> Double -> Double -> IO()
affiche2 win a b = do
renderWithDrawable win $ setSourceRGB 0 1 0
renderWithDrawable win $ setLineWidth 1
renderWithDrawable win $ C.rectangle a b 1 1
renderWithDrawable win stroke
affiche :: DrawWindow -> ((Double,Double), (Double,Double)) -> IO ()
affiche win ((a0,a), (b0,b)) = when (mandelbrot a b) $ postGUIAsync (affiche2 win a0 b0)
colonnes :: Double -> [(Double, Double)]
colonnes w = [ (t,t/w*4-2) | t<-[0..(w-1)] ]
lignes :: Double -> [(Double, Double)]
lignes h = [ (t,t/h*4-2) | t<-[0..(h-1)] ]
points :: Double -> Double -> [((Double, Double), (Double, Double))]
points w h = [ (colonne,ligne)| colonne <- colonnes w,ligne <- lignes h]
main() 没什么意思,但它确实有效,我敢肯定。
update_canvas 获取一些值(宽度、高度、win)并调用副作用函数 affiche,为它提供 "points" 中的值(points 包含好的值,即 [ -2..2] 用于 2 个轴。
mandelbrot 很好,因为我成功地绘制了 mandelbrot 集(但所有点都被绘制在一起)。
我认为如果有问题,它可能来自 affiche 或 affiche2,但我是 Gtk 编程的新手。
谢谢。
编辑
好吧,它适用于您的更改,但为什么呢?
我还有另一个问题:如果我提高参数 k(比如 1000),则该集合在启动程序后仅显示 17 秒,而且显示速度非常快;但这不是我想要的:我希望在计算点后立即绘制点。你知道我必须做什么改变吗?
编辑 2
这是一个代码
- 有效:它在 <10 秒内显示图像
- 不使用任何 UI 或 GLADE 文件
- 在计算完所有点后绘制点
module Main where
import Control.Monad (when)
import Graphics.Rendering.Cairo as C
import Graphics.UI.Gtk
import Graphics.UI.Gtk.Builder ()
main :: IO()
main = do
_ <- initGUI
window <- windowNew
windowSetPosition window WinPosCenter
windowSetDefaultSize window 500 350
set window [windowTitle := "Ensemble de Mandelbrot"]
on window objectDestroy mainQuit
canvas <- drawingAreaNew
canvas `on` sizeRequest $ return (Requisition 450 300)
window `containerAdd` canvas
_ <- onExpose canvas $ const (updateCanvas canvas)
widgetShowAll window
mainGUI
updateCanvas :: DrawingArea -> IO Bool
updateCanvas canvas = do
win <- widgetGetDrawWindow canvas
(width, height) <- widgetGetSize canvas
_ <- mapM_ (affiche win) (points (fromIntegral width) (fromIntegral height))
return True
k :: Int
k=100 -- 100 : after launching, u must wait less than 10s
mandelbrot :: Double -> Double -> Bool
mandelbrot a b =
let
mandelrec :: Double -> Double -> Int -> Bool
mandelrec x y i
| (x * x + y * y > 4) = False
| (i==k) && (x * x + y * y <= 4) = True
| otherwise = mandelrec x' y' (i+1)
where x' = x * x - y * y + a
y' = 2 * x * y + b
in mandelrec 0 0 0
affiche2 :: DrawWindow -> Double -> Double -> IO()
affiche2 win a b = renderWithDrawable win $ do
setSourceRGB 0 0 0
setLineWidth 1
C.rectangle a b 1 1
stroke
affiche :: DrawWindow -> ((Double,Double), (Double,Double)) -> IO ()
affiche win ((a0,a), (b0,b)) = when (mandelbrot a b) $ postGUIAsync (affiche2 win a0 b0)
colonnes :: Double -> [(Double, Double)]
colonnes w = [ (t,t/w*4-2) | t<-[0..(w-1)] ]
lignes :: Double -> [(Double, Double)]
lignes h = [ (t,t/h*4-2) | t<-[0..(h-1)] ]
points :: Double -> Double -> [((Double, Double), (Double, Double))]
points w h = [ (colonne,ligne)| colonne <- colonnes w,ligne <- lignes h]
奥利维耶
虽然我没有使用过 Gtk2Hs,但我想问题出在 affiche2
。尝试将其更改为:
affiche2 win a b = do
renderWithDrawable win $ do
setSourceRGB 0 1 0
setLineWidth 1
C.rectangle a b 1 1
stroke
我在 haskell 中使用 Gtk2Hs 编写了一个必须显示 mandelbrot 集的小程序。
以为没有编译错误,在canvas(点被着色的组件)中什么也没有显示...
你能帮我调试一下这个逻辑错误吗?
我的代码:
module Main where
import Control.Monad (when)
import Graphics.Rendering.Cairo as C
import Graphics.UI.Gtk
import Graphics.UI.Gtk.Builder ()
main :: IO()
main = do
_ <- initGUI
builder <- builderNew
builderAddFromFile builder "09-mandelbrot.ui"
window <- builderGetObject builder castToWindow "Figure de Mandelbrot"
canvas <- builderGetObject builder castToDrawingArea "drawingarea1"
_ <- onExpose canvas $ const (updateCanvas canvas)
widgetShowAll window
mainGUI
updateCanvas :: DrawingArea -> IO Bool
updateCanvas canvas = do
win <- widgetGetDrawWindow canvas
(width, height) <- widgetGetSize canvas
_ <- mapM_ (affiche win) (points (fromIntegral width) (fromIntegral height))
return True
k :: Int
k=100
mandelbrot :: Double -> Double -> Bool
mandelbrot a b =
let
mandelrec :: Double -> Double -> Int -> Bool
mandelrec x y i
| (x * x + y * y > 4) = False
| (i==k) && (x * x + y * y <= 4) = True
| otherwise = mandelrec x' y' (i+1)
where x' = x * x - y * y + a
y' = 2 * x * y + b
in mandelrec 0 0 0
affiche2 :: DrawWindow -> Double -> Double -> IO()
affiche2 win a b = do
renderWithDrawable win $ setSourceRGB 0 1 0
renderWithDrawable win $ setLineWidth 1
renderWithDrawable win $ C.rectangle a b 1 1
renderWithDrawable win stroke
affiche :: DrawWindow -> ((Double,Double), (Double,Double)) -> IO ()
affiche win ((a0,a), (b0,b)) = when (mandelbrot a b) $ postGUIAsync (affiche2 win a0 b0)
colonnes :: Double -> [(Double, Double)]
colonnes w = [ (t,t/w*4-2) | t<-[0..(w-1)] ]
lignes :: Double -> [(Double, Double)]
lignes h = [ (t,t/h*4-2) | t<-[0..(h-1)] ]
points :: Double -> Double -> [((Double, Double), (Double, Double))]
points w h = [ (colonne,ligne)| colonne <- colonnes w,ligne <- lignes h]
main() 没什么意思,但它确实有效,我敢肯定。 update_canvas 获取一些值(宽度、高度、win)并调用副作用函数 affiche,为它提供 "points" 中的值(points 包含好的值,即 [ -2..2] 用于 2 个轴。 mandelbrot 很好,因为我成功地绘制了 mandelbrot 集(但所有点都被绘制在一起)。 我认为如果有问题,它可能来自 affiche 或 affiche2,但我是 Gtk 编程的新手。
谢谢。
编辑
好吧,它适用于您的更改,但为什么呢? 我还有另一个问题:如果我提高参数 k(比如 1000),则该集合在启动程序后仅显示 17 秒,而且显示速度非常快;但这不是我想要的:我希望在计算点后立即绘制点。你知道我必须做什么改变吗?
编辑 2
这是一个代码 - 有效:它在 <10 秒内显示图像 - 不使用任何 UI 或 GLADE 文件 - 在计算完所有点后绘制点
module Main where
import Control.Monad (when)
import Graphics.Rendering.Cairo as C
import Graphics.UI.Gtk
import Graphics.UI.Gtk.Builder ()
main :: IO()
main = do
_ <- initGUI
window <- windowNew
windowSetPosition window WinPosCenter
windowSetDefaultSize window 500 350
set window [windowTitle := "Ensemble de Mandelbrot"]
on window objectDestroy mainQuit
canvas <- drawingAreaNew
canvas `on` sizeRequest $ return (Requisition 450 300)
window `containerAdd` canvas
_ <- onExpose canvas $ const (updateCanvas canvas)
widgetShowAll window
mainGUI
updateCanvas :: DrawingArea -> IO Bool
updateCanvas canvas = do
win <- widgetGetDrawWindow canvas
(width, height) <- widgetGetSize canvas
_ <- mapM_ (affiche win) (points (fromIntegral width) (fromIntegral height))
return True
k :: Int
k=100 -- 100 : after launching, u must wait less than 10s
mandelbrot :: Double -> Double -> Bool
mandelbrot a b =
let
mandelrec :: Double -> Double -> Int -> Bool
mandelrec x y i
| (x * x + y * y > 4) = False
| (i==k) && (x * x + y * y <= 4) = True
| otherwise = mandelrec x' y' (i+1)
where x' = x * x - y * y + a
y' = 2 * x * y + b
in mandelrec 0 0 0
affiche2 :: DrawWindow -> Double -> Double -> IO()
affiche2 win a b = renderWithDrawable win $ do
setSourceRGB 0 0 0
setLineWidth 1
C.rectangle a b 1 1
stroke
affiche :: DrawWindow -> ((Double,Double), (Double,Double)) -> IO ()
affiche win ((a0,a), (b0,b)) = when (mandelbrot a b) $ postGUIAsync (affiche2 win a0 b0)
colonnes :: Double -> [(Double, Double)]
colonnes w = [ (t,t/w*4-2) | t<-[0..(w-1)] ]
lignes :: Double -> [(Double, Double)]
lignes h = [ (t,t/h*4-2) | t<-[0..(h-1)] ]
points :: Double -> Double -> [((Double, Double), (Double, Double))]
points w h = [ (colonne,ligne)| colonne <- colonnes w,ligne <- lignes h]
奥利维耶
虽然我没有使用过 Gtk2Hs,但我想问题出在 affiche2
。尝试将其更改为:
affiche2 win a b = do
renderWithDrawable win $ do
setSourceRGB 0 1 0
setLineWidth 1
C.rectangle a b 1 1
stroke