1

このような例で。gtkとhaskellで2Dダブルバッファリングを行うにはどうすればよいですか?プリミティブをオフスクリーンバッファにレンダリングして反転させたい。このコードは、ピクセル/長方形のみをレンダリングします。ダブルバッファアプローチを使用して動きを追加したいと思います。

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
4

2 に答える 2

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
于 2011-03-15T10:25:12.580 に答える
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。これが最善の方法かどうかはわかりませんが、実際には十分に機能しているようです。これがお役に立てば幸いです。

于 2011-03-15T15:40:49.447 に答える