2011-09-09 30 views
2

当我创建两个窗口并在两个不同的线程(每个窗口一个)中重绘它们时,似乎所有绘图都转到第一个创建的窗口。它不断地在两个窗口应该显示的内容之间切换。第二个主要是黑色。使用GLUT在多个窗口中同时绘图

该代码运行良好,只有一个窗口,然后我更新它 - 插入currentWindow $= Just glWindow在设置回调函数和调用渲染方法的函数开头。

您认为问题的原因是什么?

编辑:

代码框架:

module Chart.Window where 

import Graphics.UI.GLUT hiding (Window, postRedisplay, <etc>) 
import qualified Graphics.UI.GLUT as GLUT 
import qualified Graphics.Rendering.OpenGL as GL 

data Window = Window 
    { glWindow :: GLUT.Window 
    , viewListRef :: IORef [Line] 
    } 

main = do 
    forkOS start <params1> 
    forkOS start <params2> 

start <params> = do 
    win <- new <params> 
    run win 
    mainLoop 

new :: Strict -> (Int, Int) -> (Int, Int) -> IO Window 
new name (posx, posy) (w, h) = do 
    initGLUT 
    glWindow <- createWindow name 
    currentWindow $= Just glWindow 
    windowSize $= Size (fromIntegral w) (fromIntegral h) 
    windowPosition $= Position (fromIntegral posx) (fromIntegral posy) 
    return Window {..} 

initGLUT :: IO() 
initGLUT = do 
    beenInit <- get initState 
    unless beenInit $ void getArgsAndInitialize 
    initialDisplayMode $= [WithDepthBuffer, DoubleBuffered, RGBAMode] 
    initialWindowSize $= Size 100 100 
    initialWindowPosition $= Position 100 100 
    actionOnWindowClose $= ContinueExectuion 

run :: Window -> IO() 
run [email protected]{..} = do 
    -- this will fork (with forkIO) threads 
    -- which will call "repaint" when chart needs to be updated 
    initListeners repaint 
    initCallbacks win 
    where 
    repaint :: [Line] -> IO() 
    repaint viewList = do 
    writeIORef viewListRef viewList 
    postRedisplay win 

postRedisplay Window{..} = GLUT.postRedisplay $ Just glWindow 

initCallbacks [email protected]{..} = do 
    currentWindow $= Just glWindow 
    GLUT.displayCallback $= display win 
    GLUT.idleCallback $= Just (postRedisplay win) 

display Window{..} = do 
    currentWindow $= Just glWindow 
    Size w h <- get windowSize 
    viewList <- readIORef viewListRef 
    drawChart viewList otherOptions 

reshapeCallback :: Window -> GLUT.ReshapeCallback 
reshapeCallback [email protected]{..} [email protected](Size w h) = do 
    currentWindow $= Just glWindow 
    GL.viewport $= (Position 0 0, size) 
    GL.matrixMode $= GL.Projection 
    GL.loadIdentity 
    GL.ortho2D 0 (fromIntegral w) 0 (fromIntegral h) 
    GL.matrixMode $= GL.Modelview 0 
    GL.loadIdentity 
    ... -- send command for listener thread to change internal state and postRedisplay 

drawChart viewList otherOptions = do 
    ... 
    -- chart consists of several horizontal panels. Call this for each panel: 
    glViewport 0 panelYPosition width winHeight 
    glScissor 0 panelYPosition (fromIntegral width) (fromIntegral panelHeight) 
    GL.clear [GL.ColorBuffer] 
    ... 
    -- and then for each line=(Vertex2 v1 v2) from viewList 
    GL.renderPrimitive GL.Lines $ do 
    GL.vertex v1 
    GL.vertex v2 
    ... 

BTW,当我评论这台reshapeCallback(和窗口在开始重塑),并推出了具有只有一个窗口图表行,我正好与多窗口发射相同的效果。我的意思是,(唯一)窗口大部分是空的,就好像它是第二次创建的。

+2

我想我们需要看代码。 –

+0

GLUT是否支持多线程? – hammar

+0

我有类似的问题。我使用一个线程来计算遗传算法的迭代,并在每次迭代中调用“GL.postRedisplay(Just window)”,但它没有绘制任何东西。 : -/ –

回答

0

我有类似的问题。我使用一个线程来计算遗传算法的迭代,并在每次迭代中调用“GL.postRedisplay(Just window)”,但它没有绘制任何东西。

我解决我的问题,通过调用“GL.postRedisplay(只是窗口)”从空闲功能:

idle window = CC.threadDelay (1000*500) >> GL.postRedisplay (Just window) 

不要忘记设置你这样的空闲回调函数:

GL.idleCallback GL.$= Just (idle window) >> 

CC和GL的意思是:

import qualified Control.Concurrent as CC 
import qualified Graphics.UI.GLUT as GL 
+1

感谢您的回答,我一直在等待3年:)我在开玩笑,但无论如何感谢 – modular

+0

不客气。 :) –