2011-03-13 4 views
1

예제와 같이. gtk와 haskell로 어떻게 2d 더블 버퍼링을 할 수 있습니까? 프리 머 티브를 오프 스크린 버퍼에 렌더링하고 뒤집기를 원합니다. 이 코드는 픽셀/사각형 만 렌더링합니다. 이중 버퍼 방식을 사용하여 움직임을 추가하고 싶습니다.Haskell GTK, 프리미티브를 사용한 더블 버퍼링

import Graphics.UI.Gtk 
import Graphics.UI.Gtk.Gdk.GC 
import Graphics.UI.Gtk hiding (Color, Point, Object) 

defaultFgColor :: Color 
defaultFgColor = Color 65535 65535 65535 

defaultBgColor :: Color 
defaultBgColor = Color 0 0 0 

renderScene d ev = do 
    dw  <- widgetGetDrawWindow d 
    (w, h) <- widgetGetSize d 
    gc  <- gcNew dw 
    let fg = Color (round (65535 * 205)) 
        (round (65535 * 0)) 
        (round (65535 * 0)) 
    gcSetValues gc $ newGCValues { foreground = fg } 
    drawPoint dw gc (120, 120) 
    drawPoint dw gc (22, 22) 
    drawRectangle dw gc True 20 20 20 20 
    return True 

main :: IO() 
main = do 
    initGUI 
    window <- windowNew 
    drawing <- drawingAreaNew 
    windowSetTitle window "Cells" 
    containerAdd window drawing 
    let bg = Color (round (65535 * 205)) 
        (round (65535 * 205)) 
        (round (65535 * 255)) 
    widgetModifyBg drawing StateNormal bg 
    onExpose drawing (renderScene drawing) 

    onDestroy window mainQuit 
    windowSetDefaultSize window 800 600 
    windowSetPosition window WinPosCenter 
    widgetShowAll window 
    mainGUI 
+0

정확하게 작동하지 않는 이유를 말해 줄 수 있습니까? – fuz

+0

이 코드는 픽셀 만 렌더링합니다. 이중 버퍼 방식을 사용하여 움직임을 추가하고 싶습니다. –

답변

2

이 내가 도면 영역에서 카이로와 페인트 및 깜박임을 방지하기 위해 사용하고 있습니다 것입니다. 당신의 renderScene 기능이 코드를 추가하십시오 :

-- Get the draw window (dw) and its size (w,h) 
    -- ... 

    regio <- regionRectangle $ Rectangle 0 0 w h 
    drawWindowBeginPaintRegion dw regio 

    -- Put paiting code here 
    -- .. 

    drawWindowEndPaint dw 

귀하의 최종 코드는 다음과 같이 수 :

import Graphics.UI.Gtk 
import Graphics.UI.Gtk.Gdk.GC 
import Graphics.UI.Gtk hiding (Color, Point, Object) 
import Data.IORef 

defaultFgColor :: Color 
defaultFgColor = Color 65535 65535 65535 

defaultBgColor :: Color 
defaultBgColor = Color 0 0 0 

renderScene pref d _ev = renderScene' pref d 

renderScene' :: IORef Int -> DrawingArea -> IO Bool 
renderScene' pref d = do 
    dw  <- widgetGetDrawWindow d 
    (w, h) <- widgetGetSize d 
    regio <- regionRectangle $ Rectangle 0 0 w h 

    pos <- readIORef pref 
    -- Go around, CCW, in a circle of size 20, centered at (100,100) 
    let x = 100 + round (20 * sin (fromIntegral pos * pi * 2/360)) 
     y = 100 + round (20 * cos (fromIntegral pos * pi * 2/360)) 
     pos' = (pos + 1) `mod` 360 
    writeIORef pref pos' 

    drawWindowBeginPaintRegion dw regio 
    gc  <- gcNew dw 
    let fg = Color (round (65535 * 205)) 
        (round (65535 * 0)) 
        (round (65535 * 0)) 
    gcSetValues gc $ newGCValues { foreground = fg } 
    drawPoint dw gc (120, 120) 
    drawPoint dw gc (22, 22) 
    drawRectangle dw gc True x y 20 20 
    -- Paint an extra rectangle 
    drawRectangle dw gc True 200 200 200 200 
    drawWindowEndPaint dw 
    return True 

main :: IO() 
main = do 
    initGUI 
    window <- windowNew 
    drawing <- drawingAreaNew 
    windowSetTitle window "Cells" 
    containerAdd window drawing 
    let bg = Color (round (65535 * 205)) 
        (round (65535 * 205)) 
        (round (65535 * 255)) 
    widgetModifyBg drawing StateNormal bg 

    pref <- newIORef 0 

    onExpose drawing (renderScene pref drawing) 
    timeoutAdd (renderScene' pref drawing) 10 

    onDestroy window mainQuit 
    windowSetDefaultSize window 800 600 
    windowSetPosition window WinPosCenter 
    widgetShowAll window 
    mainGUI 
+0

흥미로운 것 같습니다. 더 이상의 코드가 있습니까? 나는 그 교환을 보지 못한다. –

+1

스와핑은 drawWindowEndPaint와 함께 발생합니다. 문서에 따르면, "가장 최근에 drawWindowBeginPaintRegion을 호출하여 생성 된 배킹 스토어가 화면에 복사되고 삭제되어야 함을 나타냅니다." –

+0

원래 코드를 사용하는 코드로 수정했습니다. 그것은 원 안에 주위를 돌아 다니는 사각형을 그려 놓고 또 다른 하나는 거기에 누워 있습니다. paintRegions를 사용하지 않고 배경을 지우지 않으면 (예 : 흰색 직사각형을 칠한 경우) 깜박임이 표시됩니다. 이렇게하면 drawWindowEndPaint를 호출 할 때 모든 것이 그려집니다. –

0

ThreadScope 번 봐 가지고 생각 될 수 있습니다. 스크롤링은 이중 버퍼링에 매우 가깝게 구현됩니다.

prev_surface <- readIORef prevView 
win <- widgetGetDrawWindow timelineDrawingArea 
renderWithDrawable win $ do 

    -- Create new surface based on the old one 
    new_surface <- liftIO $ createSimilarSurface [...] 
    renderWith new_surface $ do 
    setSourceSurface prev_surface off 0 
    Cairo.rectangle [...] 
    Cairo.fill 
    [... render newly exposed stuff ...] 
    surfaceFinish new_surface 

    -- Save back new view 
    liftIO $ writeIORef prevView new_surface 

    -- Paint new view 
    setSourceSurface new_surface 0 0 
    setOperator OperatorSource 
    paint 

실제 코드는 Timeline/Render.hs에서 찾을 수 있습니다 여기에 내가 그들이 생각의 단순화 된 버전입니다. 이 방법이 최선의 방법인지는 모르지만 실제로는 충분히 잘 작동하는 것 같습니다. 이게 도움이 되길 바란다.