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


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

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

?

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


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


Редактировать:  Чтобы не тратить впустую ваше время, вот список пакетов, которые я пробовал:

  • WX  - ghci задыхается libstdc++
  • СДЛ  - переопределяет main быть макросом. Только время компиляции.
  • GLFW  (OpenGL) - Не удается запустить main дважды, что-то о «сбое, потому что он не может установить обработчик событий мыши».

33


источник


Ответы:


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

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

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

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

Sample bitmap


15



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

В отношении требований:

  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

3



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

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

$ 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)


2



Вы видели GLFW в качестве ссылки http://plucky.cs.yale.edu/soe/software1.htm


1



Дополнительная информация о Haskell + GUI + OpenGL доступна в этом разделе: http://www.haskell.org/pipermail/haskell-cafe/2011-May/091991.html


1