【问题标题】:haskell & Gtk2hs : no point is displayed in a canvas (parallel drawing)haskell & Gtk2hs : 画布中不显示任何点(平行绘图)
【发布时间】:2016-04-04 12:16:18
【问题描述】:

我使用 Gtk2Hs 在 haskell 中编写了一个小程序,它必须显示 mandelbrot 集。

以为没有编译错误,画布中什么都没有显示(点被着色的组件)...

你能帮我调试一下这个逻辑错误吗?

我的代码:

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 获取一些值(宽度、高度、胜利)并调用副作用函数 affitche,为其提供“点”中的值(点包含好的值,即 [-2..2] 之间的点的坐标对于 2 个轴。 mandelbrot 很好,因为我成功地绘制了 mandelbrot 集(但所有点都被绘制在一起)。 我认为如果有问题,它可能来自affitche 或affiche2,但我是Gtk 编程的新手。

谢谢。

编辑

嗯,它适用于您的更改,但为什么呢? 我还有一个问题:如果我将参数 k 提高(比如提高到 1000),则在启动程序后仅 17 秒就会显示该集合,并且显示速度非常快;但这不是我想要的:我希望在计算点后立即绘制这些点。你知道我必须做什么改变吗?

编辑 2

这是一个代码 - 有效:它在

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]

奥利弗

【问题讨论】:

  • 如果您摆脱了 ui 文件,这对我们会有所帮助——这在这里似乎没有必要。没有它,我们可以快速测试程序。
  • 我认为renderWithDrawable 为 cairo 创建了一个新的上下文,并且它之后的命令应该在相同的上下文中查看某些东西(在新的上下文中执行 stroke 是没有意义的在这个新环境中之前没有绘制任何东西)。
  • @leftaroundabout 好的,我一到家就做好并提供给你
  • @leftaroundabout 好的,完成了
  • @leftaroundabout 这是一个教程,如果没有安装所有工具,可以帮助您:rizwanbulbul.blogspot.fr/2010/06/…

标签: haskell concurrency gtk gtk2hs


【解决方案1】:

虽然我没有使用过 Gtk2Hs,但我想问题出在affiche2。尝试将其更改为:

affiche2 win a b = do
  renderWithDrawable win $ do
    setSourceRGB 0 1 0
    setLineWidth 1
    C.rectangle a b 1 1 
    stroke

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-15
    • 1970-01-01
    • 2015-02-09
    • 1970-01-01
    • 1970-01-01
    • 2019-08-30
    • 1970-01-01
    相关资源
    最近更新 更多