34

是否存在满足以下要求的 Haskell 图形库或绑定到外部库:

  1. 可以从 使用ghci,即我不必链接并重新启动程序。
  2. 适用于 MacOS X。(与 1 一起使用很棘手!)
  3. 可以做简单的矢量图形(线条、多边形、简单的填充和描边)。
  4. 可以将位图图像放在屏幕上。示例:blit 17x12 .bmp 图像。

?

请包含一个最小的源代码示例或对它的引用(只是屏幕上的一个窗口,可能在其中绘制一条绿线),以便我可以特别检查第 1 点和第 2 点。此外,如果这些功能请求之一更详细(例如 OpenGL + 4),请提供一个很好的参考。


PS:关于1和2,我知道enableGUI诀窍,我愿意使用它。但是,大多数库都有一个问题,即您不能main多次运行该函数,因此不符合条件。


编辑:为避免浪费您的时间,这里列出了我尝试过的软件包:

  • wx - ghci 阻塞libstdc++
  • sdl - 重新定义main为宏。仅编译时。
  • GLFW (OpenGL) - 不能运行main两次,关于“失败,因为它不能安装鼠标事件处理程序”。
4

5 回答 5

15

编辑:实际上,我不再确定。几个版本之后,GLFW 似乎不再适用于 OS X 上的 GHCi。

事实证明,GLFW+OpenGL 满足所有四个要求!

  1. 您需要使用 调用 ghci ghci -framework Carbon
  2. 您需要该EnableGUI.hs文件,您可以在此处获取。请注意,您不能将其直接加载到 GHCi 中,您必须首先对其进行编译。
  3. OpenGL 具有 2D 投影模式,您可以在其中绘制线条和多边形。
  4. 位图可以作为纹理加载并放在多边形上。

这是一个将位图放到屏幕上的小例子。位图有一些限制:它的尺寸必须是 2 的幂(这里是 256)并且它必须是一个.tga文件(这里"Bitmap.tga")。但由于支持透明度,这不是什么大问题。

您应该能够main毫无问题地多次调用。关键是你不应该调用GLFW.terminate.

import Graphics.Rendering.OpenGL as GL
import qualified Graphics.UI.GLFW as GLFW
import Graphics.Rendering.OpenGL (($=))

import Control.Monad
import EnableGUI

main = do
    enableGUI
    GLFW.initialize
    -- open window
    GLFW.openWindow (GL.Size 400 400) [GLFW.DisplayAlphaBits 8] GLFW.Window
    GLFW.windowTitle $= "Bitmap Test"

    -- enable alpha channel
    GL.blend         $= GL.Enabled
    GL.blendFunc     $= (GL.SrcAlpha, GL.OneMinusSrcAlpha)
    -- set the color to clear background
    GL.clearColor    $= GL.Color4 0.8 0.8 0.8 0

    -- set 2D orthogonal view inside windowSizeCallback because
    -- any change to the Window size should result in different
    -- OpenGL Viewport.
    GLFW.windowSizeCallback $= \ size@(GL.Size w h) ->
      do
        GL.viewport   $= (GL.Position 0 0, size)
        GL.matrixMode $= GL.Projection
        GL.loadIdentity
        GL.ortho2D 0 (realToFrac w) (realToFrac h) 0

    render <- initialize
    loop render

    GLFW.closeWindow

loop render = do
    -- draw the entire screen
    render
    -- swap buffer
    GLFW.swapBuffers
    -- check whether ESC is pressed for termination
    p <- GLFW.getKey GLFW.ESC
    unless (p == GLFW.Press) $ do
        -- sleep for 1ms to yield CPU to other applications
        GLFW.sleep 0.001
        -- only continue when the window is not closed
        windowOpenStatus <- GLFW.getParam GLFW.Opened
        unless (windowOpenStatus == False) $
            loop render

-- rendering
initialize = do
    -- load texture from file
    GL.texture GL.Texture2D $= Enabled
    [textureName] <- GL.genObjectNames 1
    GL.textureBinding GL.Texture2D $= Just textureName
    GL.textureFilter  GL.Texture2D $= ((GL.Nearest, Nothing), GL.Nearest)
    GLFW.loadTexture2D "Bitmap.tga" []

    return $ do
        GL.clear [GL.ColorBuffer]
        GL.renderPrimitive GL.Quads $ do
            GL.texCoord $ texCoord2 0 0
            GL.vertex   $ vertex3 (0) 256 0
            GL.texCoord $ texCoord2 0 1
            GL.vertex   $ vertex3 (0) (0) 0
            GL.texCoord $ texCoord2 1 1
            GL.vertex   $ vertex3 256 (0) 0
            GL.texCoord $ texCoord2 1 0
            GL.vertex   $ vertex3 256 256 0

-- type signatures to avoid ambiguity
vertex3 :: GLfloat -> GLfloat -> GLfloat -> GL.Vertex3 GLfloat
vertex3 = GL.Vertex3

texCoord2 :: GLfloat -> GLfloat -> GL.TexCoord2 GLfloat
texCoord2 = GL.TexCoord2

color3 :: GLfloat -> GLfloat -> GLfloat -> GL.Color3 GLfloat
color3 = GL.Color3

这是一个示例位图(您需要将其转换为.tga)。

示例位图

于 2011-05-07T17:23:12.933 回答
3

如果您使用 gtk2 框架的 X11 版本,Gtk2Hs 库可以满足所有要求

关于要求:

  1. 使用 X11 可以避免很多问题。
  2. gtk2通过MacPorts安装并使用 +x11 选项(默认)。(也就是说,我过去在安装 gtk2 时遇到了很多问题,但这次似乎可以了。)
  3. 如果 GTK+ 不能做到这一点,我会感到惊讶。
  4. 同上。

这是一个最小的例子

import Graphics.UI.Gtk

hello :: (ButtonClass o) => o -> IO ()
hello b = set b [buttonLabel := "Hello World"]

main :: IO ()
main = do
    initGUI
    window <- windowNew
    button <- buttonNew
    set window [windowDefaultWidth := 200, windowDefaultHeight := 200,
              containerChild := button, containerBorderWidth := 10]
    onClicked button (hello button)
    onDestroy window mainQuit
    widgetShowAll window
    mainGUI
于 2011-05-07T17:24:31.280 回答
2

截至 2014 年初,我无法在 Mac OS X 中使用@heinrich-apfelmus 答案。但是这个 GLFW-b 示例(链接)有效。

因此,请确保您拥有:

$ cabal install glfw-b

而且,如果您尝试了 Apfelmus 的回答,您可能需要

$ ghc-pkg list
$ ghc-pkg unregister GLFW-x.x.x.x

正如两者都提供的那样Graphics.UI.GLFW,您将从 ghc 获得“模棱两可的模块名称'Graphics.UI.GLFW'”。然后我只是尝试了上面的示例程序并且它工作了(Mac OS X,10.9,Mavericks)

于 2014-04-07T05:37:36.120 回答
1

您是否看过 GLFW 所引用的http://plucky.cs.yale.edu/soe/software1.htm

于 2011-05-03T20:36:02.867 回答
1

有关 Haskell+GUI+OpenGL 的更多信息,请参阅此讨论: http ://www.haskell.org/pipermail/haskell-cafe/2011-May/091991.html

于 2011-05-18T18:31:22.090 回答