haskell & Gtk2hs: на холсте не отображается ни одна точка (параллельное рисование)

Я написал небольшую программу, которая должна отображать множество Мандельброта на хаскеле, используя Gtk2Hs.

думал, что нет ошибки компиляции, ничего не отображается на холсте (компонент, в котором точки окрашены)...

не могли бы вы помочь мне отладить эту логическую ошибку?

мой код:

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 получает некоторые значения (width, height, win) и вызывает функцию побочного эффекта, affiche, предоставляя ей значения в «точках» (точки содержат правильные значения, а именно координаты точек между [-2..2] для 2-х осей.мандельброт хорош, так как мне удалось нарисовать множество мандельброта (все же точки были нарисованы вместе).я думаю, если есть проблема, она может исходить от аффиша или аффиша2, но я новичок в программировании Gtk .

Спасибо.

РЕДАКТИРОВАТЬ

Ну, это работает с вашим изменением, но почему? и у меня есть еще вопрос: если я подниму параметр k (скажем до 1000), набор отображается только через 17 секунд после запуска программы, и отображается очень быстро; но это не то, что я хотел бы: я хочу, чтобы точки рисовались, как только они вычисляются. Знаете ли вы, какие изменения я должен сделать?

РЕДАКТИРОВАТЬ 2

вот код, который работает: он отображает изображение в ‹10s - не использует какой-либо пользовательский интерфейс или файл 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]

оливье


person lolveley    schedule 04.04.2016    source источник
comment
Для нас было бы полезно, если бы вы избавились от файла ui — здесь это не кажется необходимым. Без него мы могли бы просто быстро протестировать программу.   -  person leftaroundabout    schedule 04.04.2016
comment
Я думаю, что renderWithDrawable создает новый контекст для cairo, и команды после него должны быть в том же контексте, чтобы что-то увидеть (нет смысла делать stroke в новом контексте, когда до этого в этом новом контексте ничего не рисовалось).   -  person MichaelO    schedule 04.04.2016
comment
@leftaroundabout хорошо, я сделаю это и предоставлю вам, как только буду дома   -  person lolveley    schedule 04.04.2016
comment
@leftaroundabout хорошо, готово   -  person lolveley    schedule 04.04.2016
comment
@leftaroundabout вот руководство, которое может помочь вам, если не установлены все инструменты: rizwanbulbul.blogspot.fr/2010/06/   -  person lolveley    schedule 04.04.2016
comment
... и вот еще один, который, я думаю, лучше: pamiz.wordpress.com/2012/12/11/   -  person lolveley    schedule 04.04.2016
comment
Итак... какая часть вопроса остается? — Вам не нужно добавлять информацию о том, как устанавливать пакеты, просто старайтесь, чтобы ваши сообщения были короткими, сфокусированными, а ваш собственный код — самодостаточным (как второй пример, сейчас; очень хорошо).   -  person leftaroundabout    schedule 04.04.2016
comment
@leftaroundabout Я бы хотел, чтобы моя программа отображала точки постепенно: теперь они все отображаются вместе после вычисления. Для данного конкретного примера это не кажется важным, но для некоторых других программ, которым требуется больше времени для вычислений, это может стать очень важным.   -  person lolveley    schedule 04.04.2016
comment
Мы могли бы продолжить с другим вопросом, так как нам нужно выбрать только один, а название другого лучше всего подходит к оставшейся задаче!   -  person lolveley    schedule 04.04.2016


Ответы (1)


Хотя я не работал с Gtk2Hs, думаю проблема в affiche2. Попробуйте изменить его на это:

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