当我创建两个窗口并在两个不同的线程(每个窗口一个)中重绘它们时,似乎所有绘图都转到第一个创建的窗口。它不断在两个窗口中显示的内容之间切换。第二个仍然是黑色。
代码只用了一个窗口,然后我更新了它 - 在设置回调和调用渲染方法的函数的开头插入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 win@Window{..} = 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 win@Window{..} = 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 win@Window{..} size@(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
...
顺便说一下,当我评论设置reshapeCallback的行(并且窗口在开头重新整形)并仅使用一个窗口启动图表时,我得到了与多窗口启动完全相同的效果。我的意思是,(唯一)窗口大部分都是空的,好像它是第二次创建的那样。
答案 0 :(得分:0)
我有类似的问题。我使用一个计算遗传算法迭代的线程,并在每次迭代中调用“GL.postRedisplay(Just window)”,但它没有绘制任何东西。
我通过从空闲功能调用“GL.postRedisplay(Just window)”解决了我的问题:
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