Подтвердить что ты не робот

Графическая библиотека Haskell, работающая в GHCi на MacOS X

Существует ли графическая библиотека Haskell или привязка к внешней библиотеке, которая удовлетворяет следующим требованиям:

  • Может использоваться из ghci, т.е. мне не нужно связывать и перезапускать программу.
  • Работает на MacOS X. (Tricky в сочетании с 1!)
  • Может выполнять простую векторную графику (линии, полигоны, простые заливки и штрихи).
  • Можно поместить растровые изображения на экран. Пример: blit изображение 17x12.bmp.

?

Пожалуйста, укажите минимальный пример исходного кода или ссылку на него (просто окно на экране, возможно, с зеленой линией, нарисованной внутри него), чтобы я мог проверить точки 1. и 2. в частности. Кроме того, если один из этих запросов функций более сложный (например, OpenGL + 4), пожалуйста, добавьте хорошую ссылку.


PS: Что касается 1 и 2, я знаю об трюке enableGUI, и я готов его использовать. Однако в большинстве библиотек проблема состоит в том, что вы не можете запускать функцию main несколько раз и, следовательно, не квалифицироваться.


Изменить: Чтобы избежать потери времени, вот список пакетов, которые я пробовал:

  • wx - ghci дросселирует на libstdc++
  • sdl - переопределяет main как макрос. Только время компиляции.
  • GLFW (OpenGL) - не удается запустить main дважды, что-то о "сбое, потому что он не может установить событие мыши обработчик".
4b9b3361

Ответ 1

EDIT: Вообще-то, я не уверен. Несколько версий позже, похоже, GLFW больше не работает в GHCi на OS X.

Оказывается, GLFW + OpenGL выполняет все четыре требования!

  • Вам нужно вызвать ghci с помощью ghci -framework Carbon.
  • Вам нужен файл EnableGUI.hs, который вы можете получить здесь. Обратите внимание, что вы не можете загрузить его прямо в GHCi, сначала вам нужно соединить его.
  • OpenGL имеет режим 2D-проекции, где вы можете рисовать линии и полигоны.
  • Растровые изображения могут быть загружены как текстуры и наложены на многоугольники.

Вот небольшой пример, который помещает растровое изображение на экран. Существуют некоторые ограничения на растровое изображение: его размеры должны быть равны двум (здесь 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 $= \ [email protected](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).

Sample bitmap

Ответ 2

Библиотека Gtk2Hs удовлетворяет всем требованиям, если вы используете версию X12 версии xk2.

Относительно требований:

  • Использование X11 позволяет избежать многих проблем.
  • Установите gtk2 через MacPorts и используйте опцию + x11 (по умолчанию). (Тем не менее, у меня было множество проблем с установкой gtk2 в прошлом, но на этот раз это работало.)
  • Я был бы удивлен, если GTK + не может этого сделать.
  • То же.

Здесь минимальный пример

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

Ответ 3

С начала 2014 года я не смог использовать ответ @heinrich-apfelmus в Mac OS X. Этот пример GLFW-b (link), однако работал.

Итак, убедитесь, что у вас есть:

$ cabal install glfw-b

и, если вы попробовали ответить Apfelmus, вам может понадобиться

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

поскольку оба предоставляют Graphics.UI.GLFW, и вы получите "Неоднозначное имя модуля" Graphics.UI.GLFW "из ghc. Затем я просто попробовал образец программы выше, и он работал (Mac OS X, 10.9, Mavericks)