Я написал небольшую программу, которая должна отображать множество Мандельброта на хаскеле, используя 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]
оливье
renderWithDrawable
создает новый контекст для cairo, и команды после него должны быть в том же контексте, чтобы что-то увидеть (нет смысла делатьstroke
в новом контексте, когда до этого в этом новом контексте ничего не рисовалось). - person MichaelO   schedule 04.04.2016