Haskell Graphics Library, która działa w GHCi na MacOS X

Czy istnieje Biblioteka graficzna Haskell lub powiązanie z biblioteką zewnętrzną, która spełnia następujące wymagania:

  1. Można używać z ghci, tzn. nie muszę linkować i restartować programu.
  2. działa na MacOS X. (Tricky w połączeniu z 1!)
  3. potrafi wykonywać proste grafiki wektorowe (linie, wielokąty, proste wypełnienia i obrysy).
  4. może umieszczać obrazy bitmapowe na ekranie. Przykład: blit a 17x12 .obraz bmp.

?

Proszę dołączyć minimalny przykład kodu źródłowego lub odniesienie do niego (tylko okno na ekranie, może z zieloną linią narysowaną wewnątrz), żebym mógł sprawdzić punkty 1. i 2. w szczególności. Ponadto, jeśli jedno z tych żądań funkcji jest bardziej rozbudowane (na przykład OpenGL + 4), proszę podać dobre odniesienie.


PS: co do 1 i 2 to Wiem o sztuczce enableGUI i jestem skłonny jej użyć. Jednak większość bibliotek ma problem, że nie można uruchomić funkcji main wiele razy i dlatego nie / align = "left" /


Edit: aby uniknąć marnowania czasu, oto lista pakietów, które wypróbowałem:

  • WX - ghci dławi się na libstdc++
  • sdl - redefiniuje main jako makro. Tylko czas kompilacji.
  • GLFW (OpenGL) - nie można uruchomić main dwa razy, coś o "niepowodzeniu, ponieważ nie można zainstalować obsługi zdarzeń myszy".
Author: Heinrich Apfelmus, 2011-05-03

5 answers

EDIT: właściwie, nie jestem już pewien. Kilka wersji później wydaje się, że GLFW nie działa już w GHCi na OS X.

Okazuje się, że GLFW+OpenGL spełnia wszystkie cztery wymagania!

  1. musisz wywołać ghci za pomocą ghci -framework Carbon.
  2. potrzebujesz pliku EnableGUI.hs, który możesz pobrać tutaj . Zauważ, że nie możesz załadować go bezpośrednio do GHCi, najpierw musisz go załadować.
  3. OpenGL posiada tryb projekcji 2D, w którym można rysować linie i wielokąty.
  4. bitmapy mogą być ładowane jako tekstury i umieszczane na wielokątach.

Oto mały przykład, który umieszcza bitmapę na ekranie. Istnieją pewne ograniczenia dotyczące bitmapy: jej wymiary muszą mieć moc dwóch (tutaj 256) I musi to być Plik .tga (TUTAJ "Bitmap.tga"). Ale ponieważ przejrzystość jest wspierana, nie stanowi to większego problemu.

Powinieneś być w stanie zadzwonić main wiele razy bez problemu. Najważniejsze jest to, że nie powinieneś dzwonić 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

Oto przykładowa bitmapa (którą musisz przekonwertować na .tga).

Przykładowa bitmapa

 15
Author: Heinrich Apfelmus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-20 12:27:00

Biblioteka Gtk2Hs spełnia wszystkie wymagania, jeśli używasz wersji X11 frameworka gtk2.

Dotyczące wymagań:

  1. używanie X11 pozwala uniknąć wielu problemów.
  2. zainstaluj gtk2przez MacPorts i użyj opcji +x11 (domyślnie). (To powiedziawszy, miałem wiele problemów z instalacją gtk2 w przeszłości, ale tym razem wydawało się, że działa.)
  3. Zdziwiłbym się, gdyby GTK+ tego nie potrafiło. Ja też.

Tutaj minimum przykład

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
Author: Heinrich Apfelmus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-07 17:24:31

Na początku 2014 roku nie byłem w stanie użyć odpowiedzi @heinrich-apfelmus w Mac OS X. Ten przykład GLFW-B (link ) jednak zadziałał.

Więc upewnij się, że masz:

$ cabal install glfw-b

I, jeśli próbowałeś odpowiedzi Apfelmusa, być może będziesz musiał

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

Ponieważ oba zapewniają Graphics.UI.GLFW, a otrzymasz grafikę "niejednoznaczną nazwę modułu".UI.GLFW "" z ghc. Następnie wypróbowałem przykładowy program powyżej i zadziałał (Mac OS X, 10.9, Mavericks)

 2
Author: carlosayam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-09 11:11:04

Czy widziałeś GLFW jako odniesienie http://plucky.cs.yale.edu/soe/software1.htm

 1
Author: Grady Player,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-03 20:36:02

Więcej informacji na temat Haskell + GUI + OpenGL jest dostępna w tej dyskusji: http://www.haskell.org/pipermail/haskell-cafe/2011-May/091991.html

 1
Author: amindfv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-18 18:31:22